--- a/.hgtags Wed Jun 26 14:28:47 2019 +0530
+++ b/.hgtags Fri Jun 28 14:36:42 2019 +0530
@@ -567,3 +567,5 @@
2f4e214781a1d597ed36bf5a36f20928c6c82996 jdk-14+1
0692b67f54621991ba7afbf23e55b788f3555e69 jdk-13+26
43627549a488b7d0b4df8fad436e36233df89877 jdk-14+2
+b7f68ddec66f996ae3aad03291d129ca9f02482d jdk-13+27
+e64383344f144217c36196c3c8a2df8f588a2af3 jdk-14+3
--- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -63,27 +63,25 @@
return;
}
- // rscratch1 can be passed as src or dst, so don't use it.
- RegSet savedRegs = RegSet::of(rscratch2, rheapbase);
+ assert_different_registers(rscratch1, rscratch2, src.base());
+ assert_different_registers(rscratch1, rscratch2, dst);
+
+ RegSet savedRegs = RegSet::range(r0,r28) - RegSet::of(dst, rscratch1, rscratch2);
Label done;
- assert_different_registers(rheapbase, rscratch2, dst);
- assert_different_registers(rheapbase, rscratch2, src.base());
-
- __ push(savedRegs, sp);
// Load bad mask into scratch register.
- __ ldr(rheapbase, address_bad_mask_from_thread(rthread));
+ __ ldr(rscratch1, address_bad_mask_from_thread(rthread));
__ lea(rscratch2, src);
__ ldr(dst, src);
// Test reference against bad mask. If mask bad, then we need to fix it up.
- __ tst(dst, rheapbase);
+ __ tst(dst, rscratch1);
__ br(Assembler::EQ, done);
__ enter();
- __ push(RegSet::range(r0,r28) - RegSet::of(dst), sp);
+ __ push(savedRegs, sp);
if (c_rarg0 != dst) {
__ mov(c_rarg0, dst);
@@ -91,13 +89,15 @@
__ mov(c_rarg1, rscratch2);
int step = 4 * wordSize;
- __ mov(rscratch1, -step);
+ __ mov(rscratch2, -step);
__ sub(sp, sp, step);
for (int i = 28; i >= 4; i -= 4) {
__ st1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
- as_FloatRegister(i+3), __ T1D, Address(__ post(sp, rscratch1)));
+ as_FloatRegister(i+3), __ T1D, Address(__ post(sp, rscratch2)));
}
+ __ st1(as_FloatRegister(0), as_FloatRegister(1), as_FloatRegister(2),
+ as_FloatRegister(3), __ T1D, Address(sp));
__ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2);
@@ -111,13 +111,10 @@
__ mov(dst, r0);
}
- __ pop(RegSet::range(r0,r28) - RegSet::of(dst), sp);
+ __ pop(savedRegs, sp);
__ leave();
__ bind(done);
-
- // Restore tmps
- __ pop(savedRegs, sp);
}
#ifdef ASSERT
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -886,8 +886,8 @@
}
// Get mirror and store it in the frame as GC root for this Method*
- __ load_mirror(rscratch1, rmethod);
- __ stp(rscratch1, zr, Address(sp, 4 * wordSize));
+ __ load_mirror(r10, rmethod);
+ __ stp(r10, zr, Address(sp, 4 * wordSize));
__ ldr(rcpool, Address(rmethod, Method::const_offset()));
__ ldr(rcpool, Address(rcpool, ConstMethod::constants_offset()));
--- a/src/hotspot/share/ci/ciMethodData.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/ci/ciMethodData.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -81,13 +81,13 @@
// Check for entries that reference an unloaded method
class PrepareExtraDataClosure : public CleanExtraDataClosure {
MethodData* _mdo;
- uint64_t _safepoint_counter;
+ SafepointStateTracker _safepoint_tracker;
GrowableArray<Method*> _uncached_methods;
public:
PrepareExtraDataClosure(MethodData* mdo)
: _mdo(mdo),
- _safepoint_counter(SafepointSynchronize::safepoint_counter()),
+ _safepoint_tracker(SafepointSynchronize::safepoint_state_tracker()),
_uncached_methods()
{ }
@@ -103,7 +103,7 @@
}
bool has_safepointed() {
- return SafepointSynchronize::safepoint_counter() != _safepoint_counter;
+ return _safepoint_tracker.safepoint_state_changed();
}
bool finish() {
--- a/src/hotspot/share/code/dependencyContext.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/code/dependencyContext.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -99,15 +99,15 @@
// Safepoints are forbidden during DC lifetime. GC can invalidate
// _dependency_context_addr if it relocates the holder
// (e.g. CallSiteContext Java object).
- uint64_t _safepoint_counter;
+ SafepointStateTracker _safepoint_tracker;
DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
: _dependency_context_addr(bucket_addr),
_last_cleanup_addr(last_cleanup_addr),
- _safepoint_counter(SafepointSynchronize::safepoint_counter()) {}
+ _safepoint_tracker(SafepointSynchronize::safepoint_state_tracker()) {}
~DependencyContext() {
- assert(SafepointSynchronize::is_same_safepoint(_safepoint_counter), "must be the same safepoint");
+ assert(!_safepoint_tracker.safepoint_state_changed(), "must be the same safepoint");
}
#else
DependencyContext(nmethodBucket* volatile* bucket_addr, volatile uint64_t* last_cleanup_addr)
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -4250,7 +4250,6 @@
if (should_unload_classes()) {
heap->prune_scavengable_nmethods();
}
- JvmtiExport::gc_epilogue();
// If we encountered any (marking stack / work queue) overflow
// events during the current CMS cycle, take appropriate
--- a/src/hotspot/share/gc/g1/g1Analytics.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1Analytics.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -38,7 +38,7 @@
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
};
-static double cost_per_card_ms_defaults[] = {
+static double cost_per_log_buffer_entry_ms_defaults[] = {
0.01, 0.005, 0.005, 0.003, 0.003, 0.002, 0.002, 0.0015
};
@@ -47,7 +47,7 @@
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};
-static double cost_per_entry_ms_defaults[] = {
+static double young_only_cost_per_remset_card_ms_defaults[] = {
0.015, 0.01, 0.01, 0.008, 0.008, 0.0055, 0.0055, 0.005
};
@@ -77,12 +77,12 @@
_alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_prev_collection_pause_end_ms(0.0),
_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
- _cost_per_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+ _cost_per_log_buffer_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_scan_hcc_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
- _cost_per_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
- _mixed_cost_per_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+ _young_only_cost_per_remset_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
+ _mixed_cost_per_remset_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_byte_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_constant_other_time_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
@@ -101,10 +101,10 @@
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]);
+ _cost_per_log_buffer_entry_ms_seq->add(cost_per_log_buffer_entry_ms_defaults[index]);
_cost_scan_hcc_seq->add(0.0);
_young_cards_per_entry_ratio_seq->add(young_cards_per_entry_ratio_defaults[index]);
- _cost_per_entry_ms_seq->add(cost_per_entry_ms_defaults[index]);
+ _young_only_cost_per_remset_card_ms_seq->add(young_only_cost_per_remset_card_ms_defaults[index]);
_cost_per_byte_ms_seq->add(cost_per_byte_ms_defaults[index]);
_constant_other_time_ms_seq->add(constant_other_time_ms_defaults[index]);
_young_other_cost_per_region_ms_seq->add(young_other_cost_per_region_ms_defaults[index]);
@@ -158,19 +158,19 @@
(pause_time_ms * _recent_prev_end_times_for_all_gcs_sec->num()) / interval_ms;
}
-void G1Analytics::report_cost_per_card_ms(double cost_per_card_ms) {
- _cost_per_card_ms_seq->add(cost_per_card_ms);
+void G1Analytics::report_cost_per_log_buffer_entry_ms(double cost_per_log_buffer_entry_ms) {
+ _cost_per_log_buffer_entry_ms_seq->add(cost_per_log_buffer_entry_ms);
}
void G1Analytics::report_cost_scan_hcc(double cost_scan_hcc) {
_cost_scan_hcc_seq->add(cost_scan_hcc);
}
-void G1Analytics::report_cost_per_entry_ms(double cost_per_entry_ms, bool for_young_gc) {
+void G1Analytics::report_cost_per_remset_card_ms(double cost_per_remset_card_ms, bool for_young_gc) {
if (for_young_gc) {
- _cost_per_entry_ms_seq->add(cost_per_entry_ms);
+ _young_only_cost_per_remset_card_ms_seq->add(cost_per_remset_card_ms);
} else {
- _mixed_cost_per_entry_ms_seq->add(cost_per_entry_ms);
+ _mixed_cost_per_remset_card_ms_seq->add(cost_per_remset_card_ms);
}
}
@@ -222,8 +222,8 @@
return get_new_prediction(_alloc_rate_ms_seq);
}
-double G1Analytics::predict_cost_per_card_ms() const {
- return get_new_prediction(_cost_per_card_ms_seq);
+double G1Analytics::predict_cost_per_log_buffer_entry_ms() const {
+ return get_new_prediction(_cost_per_log_buffer_entry_ms_seq);
}
double G1Analytics::predict_scan_hcc_ms() const {
@@ -231,7 +231,7 @@
}
double G1Analytics::predict_rs_update_time_ms(size_t pending_cards) const {
- return pending_cards * predict_cost_per_card_ms() + predict_scan_hcc_ms();
+ return pending_cards * predict_cost_per_log_buffer_entry_ms() + predict_scan_hcc_ms();
}
double G1Analytics::predict_young_cards_per_entry_ratio() const {
@@ -256,17 +256,17 @@
double G1Analytics::predict_rs_scan_time_ms(size_t card_num, bool for_young_gc) const {
if (for_young_gc) {
- return card_num * get_new_prediction(_cost_per_entry_ms_seq);
+ return card_num * get_new_prediction(_young_only_cost_per_remset_card_ms_seq);
} else {
return predict_mixed_rs_scan_time_ms(card_num);
}
}
double G1Analytics::predict_mixed_rs_scan_time_ms(size_t card_num) const {
- if (_mixed_cost_per_entry_ms_seq->num() < 3) {
- return card_num * get_new_prediction(_cost_per_entry_ms_seq);
+ if (_mixed_cost_per_remset_card_ms_seq->num() < 3) {
+ return card_num * get_new_prediction(_young_only_cost_per_remset_card_ms_seq);
} else {
- return card_num * get_new_prediction(_mixed_cost_per_entry_ms_seq);
+ return card_num * get_new_prediction(_mixed_cost_per_remset_card_ms_seq);
}
}
--- a/src/hotspot/share/gc/g1/g1Analytics.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1Analytics.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -46,12 +46,12 @@
double _prev_collection_pause_end_ms;
TruncatedSeq* _rs_length_diff_seq;
- TruncatedSeq* _cost_per_card_ms_seq;
+ TruncatedSeq* _cost_per_log_buffer_entry_ms_seq;
TruncatedSeq* _cost_scan_hcc_seq;
TruncatedSeq* _young_cards_per_entry_ratio_seq;
TruncatedSeq* _mixed_cards_per_entry_ratio_seq;
- TruncatedSeq* _cost_per_entry_ms_seq;
- TruncatedSeq* _mixed_cost_per_entry_ms_seq;
+ TruncatedSeq* _young_only_cost_per_remset_card_ms_seq;
+ TruncatedSeq* _mixed_cost_per_remset_card_ms_seq;
TruncatedSeq* _cost_per_byte_ms_seq;
TruncatedSeq* _constant_other_time_ms_seq;
TruncatedSeq* _young_other_cost_per_region_ms_seq;
@@ -99,9 +99,9 @@
void report_concurrent_mark_remark_times_ms(double ms);
void report_concurrent_mark_cleanup_times_ms(double ms);
void report_alloc_rate_ms(double alloc_rate);
- void report_cost_per_card_ms(double cost_per_card_ms);
+ void report_cost_per_log_buffer_entry_ms(double cost_per_log_buffer_entry_ms);
void report_cost_scan_hcc(double cost_scan_hcc);
- void report_cost_per_entry_ms(double cost_per_entry_ms, bool for_young_gc);
+ void report_cost_per_remset_card_ms(double cost_per_remset_card_ms, bool for_young_gc);
void report_cards_per_entry_ratio(double cards_per_entry_ratio, bool for_young_gc);
void report_rs_length_diff(double rs_length_diff);
void report_cost_per_byte_ms(double cost_per_byte_ms, bool mark_or_rebuild_in_progress);
@@ -116,7 +116,7 @@
double predict_alloc_rate_ms() const;
int num_alloc_rate_ms() const;
- double predict_cost_per_card_ms() const;
+ double predict_cost_per_log_buffer_entry_ms() const;
double predict_scan_hcc_ms() const;
--- a/src/hotspot/share/gc/g1/g1CardTable.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CardTable.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -30,28 +30,6 @@
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
-bool G1CardTable::mark_card_deferred(size_t card_index) {
- CardValue val = _byte_map[card_index];
- // It's already processed
- if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
- return false;
- }
-
- // Cached bit can be installed either on a clean card or on a claimed card.
- CardValue new_val = val;
- if (val == clean_card_val()) {
- new_val = deferred_card_val();
- } else {
- if (val & claimed_card_val()) {
- new_val = val | deferred_card_val();
- }
- }
- if (new_val != val) {
- Atomic::cmpxchg(new_val, &_byte_map[card_index], val);
- }
- return true;
-}
-
void G1CardTable::g1_mark_as_young(const MemRegion& mr) {
CardValue *const first = byte_for(mr.start());
CardValue *const last = byte_after(mr.last());
--- a/src/hotspot/share/gc/g1/g1CardTable.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CardTable.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -44,55 +44,65 @@
virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled);
};
-class G1CardTable: public CardTable {
+class G1CardTable : public CardTable {
friend class VMStructs;
friend class G1CardTableChangedListener;
G1CardTableChangedListener _listener;
+public:
enum G1CardValues {
- g1_young_gen = CT_MR_BS_last_reserved << 1
+ g1_young_gen = CT_MR_BS_last_reserved << 1,
+
+ // During evacuation we use the card table to consolidate the cards we need to
+ // scan for roots onto the card table from the various sources. Further it is
+ // used to record already completely scanned cards to avoid re-scanning them
+ // when incrementally evacuating the old gen regions of a collection set.
+ // This means that already scanned cards should be preserved.
+ //
+ // The merge at the start of each evacuation round simply sets cards to dirty
+ // that are clean; scanned cards are set to 0x1.
+ //
+ // This means that the LSB determines what to do with the card during evacuation
+ // given the following possible values:
+ //
+ // 11111111 - clean, do not scan
+ // 00000001 - already scanned, do not scan
+ // 00000000 - dirty, needs to be scanned.
+ //
+ g1_card_already_scanned = 0x1
};
-public:
+ static const size_t WordAllClean = SIZE_MAX;
+ static const size_t WordAllDirty = 0;
+
+ STATIC_ASSERT(BitsPerByte == 8);
+ static const size_t WordAlreadyScanned = (SIZE_MAX / 255) * g1_card_already_scanned;
+
G1CardTable(MemRegion whole_heap): CardTable(whole_heap, /* scanned concurrently */ true), _listener() {
_listener.set_card_table(this);
}
- bool is_card_dirty(size_t card_index) {
- return _byte_map[card_index] == dirty_card_val();
- }
static CardValue g1_young_card_val() { return g1_young_gen; }
-/*
- Claimed and deferred bits are used together in G1 during the evacuation
- pause. These bits can have the following state transitions:
- 1. The claimed bit can be put over any other card state. Except that
- the "dirty -> dirty and claimed" transition is checked for in
- G1 code and is not used.
- 2. Deferred bit can be set only if the previous state of the card
- was either clean or claimed. mark_card_deferred() is wait-free.
- We do not care if the operation is be successful because if
- it does not it will only result in duplicate entry in the update
- buffer because of the "cache-miss". So it's not worth spinning.
- */
-
- bool is_card_claimed(size_t card_index) {
- CardValue val = _byte_map[card_index];
- return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
- }
-
- inline void set_card_claimed(size_t card_index);
-
void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN;
void g1_mark_as_young(const MemRegion& mr);
- bool mark_card_deferred(size_t card_index);
+ size_t index_for_cardvalue(CardValue const* p) const {
+ return pointer_delta(p, _byte_map, sizeof(CardValue));
+ }
+
+ // Mark the given card as Dirty if it is Clean.
+ inline void mark_clean_as_dirty(size_t card_index);
- bool is_card_deferred(size_t card_index) {
- CardValue val = _byte_map[card_index];
- return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
- }
+ // Change Clean cards in a (large) area on the card table as Dirty, preserving
+ // already scanned cards. Assumes that most cards in that area are Clean.
+ inline void mark_region_dirty(size_t start_card_index, size_t num_cards);
+
+ // Mark the given range of cards as Scanned. All of these cards must be Dirty.
+ inline void mark_as_scanned(size_t start_card_index, size_t num_cards);
+
+ inline uint region_idx_for(CardValue* p);
static size_t compute_size(size_t mem_region_size_in_words) {
size_t number_of_slots = (mem_region_size_in_words / card_size_in_words);
--- a/src/hotspot/share/gc/g1/g1CardTable.inline.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CardTable.inline.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -26,15 +26,58 @@
#define SHARE_GC_G1_G1CARDTABLE_INLINE_HPP
#include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/heapRegion.hpp"
-void G1CardTable::set_card_claimed(size_t card_index) {
- jbyte val = _byte_map[card_index];
- if (val == clean_card_val()) {
- val = (jbyte)claimed_card_val();
- } else {
- val |= (jbyte)claimed_card_val();
+inline uint G1CardTable::region_idx_for(CardValue* p) {
+ size_t const card_idx = pointer_delta(p, _byte_map, sizeof(CardValue));
+ return (uint)(card_idx >> (HeapRegion::LogOfHRGrainBytes - card_shift));
+}
+
+inline void G1CardTable::mark_clean_as_dirty(size_t card_index) {
+ CardValue value = _byte_map[card_index];
+ if (value == clean_card_val()) {
+ _byte_map[card_index] = dirty_card_val();
}
- _byte_map[card_index] = val;
}
-#endif // SHARE_GC_G1_G1CARDTABLE_INLINE_HPP
+inline void G1CardTable::mark_region_dirty(size_t start_card_index, size_t num_cards) {
+ assert(is_aligned(start_card_index, sizeof(size_t)), "Start card index must be aligned.");
+ assert(is_aligned(num_cards, sizeof(size_t)), "Number of cards to change must be evenly divisible.");
+
+ size_t const num_chunks = num_cards / sizeof(size_t);
+
+ size_t* cur_word = (size_t*)&_byte_map[start_card_index];
+ size_t* const end_word_map = cur_word + num_chunks;
+ while (cur_word < end_word_map) {
+ size_t value = *cur_word;
+ if (value == WordAllClean) {
+ *cur_word = WordAllDirty;
+ } else if (value == WordAllDirty) {
+ // do nothing.
+ } else {
+ // There is a mix of cards in there. Tread slowly.
+ CardValue* cur = (CardValue*)cur_word;
+ for (size_t i = 0; i < sizeof(size_t); i++) {
+ CardValue value = *cur;
+ if (value == clean_card_val()) {
+ *cur = dirty_card_val();
+ }
+ cur++;
+ }
+ }
+ cur_word++;
+ }
+}
+
+inline void G1CardTable::mark_as_scanned(size_t start_card_index, size_t num_cards) {
+ CardValue* start = &_byte_map[start_card_index];
+ CardValue* const end = start + num_cards;
+ while (start < end) {
+ CardValue value = *start;
+ assert(value == dirty_card_val(),
+ "Must have been dirty %d start " PTR_FORMAT " " PTR_FORMAT, value, p2i(start), p2i(end));
+ *start++ = g1_card_already_scanned;
+ }
+}
+
+#endif /* SHARE_GC_G1_G1CARDTABLE_INLINE_HPP */
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -1677,7 +1677,6 @@
_card_table = ct;
G1BarrierSet::satb_mark_queue_set().initialize(this,
- SATB_Q_CBL_mon,
&bs->satb_mark_queue_buffer_allocator(),
G1SATBProcessCompletedThreshold,
G1SATBBufferEnqueueingThresholdPercent);
@@ -1955,7 +1954,7 @@
n_completed_buffers++;
}
assert(dcqs.completed_buffers_num() == 0, "Completed buffers exist!");
- phase_times()->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, n_completed_buffers, G1GCPhaseTimes::UpdateRSProcessedBuffers);
+ phase_times()->record_thread_work_item(G1GCPhaseTimes::MergeLB, worker_i, n_completed_buffers, G1GCPhaseTimes::MergeLBProcessedBuffers);
}
// Computes the sum of the storage used by the various regions.
@@ -2239,8 +2238,8 @@
_collection_set.iterate(cl);
}
-void G1CollectedHeap::collection_set_iterate_increment_from(HeapRegionClosure *cl, uint worker_id) {
- _collection_set.iterate_incremental_part_from(cl, worker_id, workers()->active_workers());
+void G1CollectedHeap::collection_set_iterate_increment_from(HeapRegionClosure *cl, HeapRegionClaimer* hr_claimer, uint worker_id) {
+ _collection_set.iterate_incremental_part_from(cl, hr_claimer, worker_id, workers()->active_workers());
}
HeapWord* G1CollectedHeap::block_start(const void* addr) const {
@@ -2631,8 +2630,6 @@
size_t _total_humongous;
size_t _candidate_humongous;
- G1DirtyCardQueue _dcq;
-
bool humongous_region_is_candidate(G1CollectedHeap* g1h, HeapRegion* region) const {
assert(region->is_starts_humongous(), "Must start a humongous object");
@@ -2692,8 +2689,7 @@
public:
RegisterRegionsWithRegionAttrTableClosure()
: _total_humongous(0),
- _candidate_humongous(0),
- _dcq(&G1BarrierSet::dirty_card_queue_set()) {
+ _candidate_humongous(0) {
}
virtual bool do_heap_region(HeapRegion* r) {
@@ -2708,49 +2704,9 @@
uint rindex = r->hrm_index();
g1h->set_humongous_reclaim_candidate(rindex, is_candidate);
if (is_candidate) {
+ g1h->register_humongous_region_with_region_attr(rindex);
_candidate_humongous++;
- g1h->register_humongous_region_with_region_attr(rindex);
- // Is_candidate already filters out humongous object with large remembered sets.
- // If we have a humongous object with a few remembered sets, we simply flush these
- // remembered set entries into the DCQS. That will result in automatic
- // re-evaluation of their remembered set entries during the following evacuation
- // phase.
- if (!r->rem_set()->is_empty()) {
- guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries),
- "Found a not-small remembered set here. This is inconsistent with previous assumptions.");
- G1CardTable* ct = g1h->card_table();
- HeapRegionRemSetIterator hrrs(r->rem_set());
- size_t card_index;
- while (hrrs.has_next(card_index)) {
- CardTable::CardValue* card_ptr = ct->byte_for_index(card_index);
- // The remembered set might contain references to already freed
- // regions. Filter out such entries to avoid failing card table
- // verification.
- if (g1h->is_in(ct->addr_for(card_ptr))) {
- if (*card_ptr != G1CardTable::dirty_card_val()) {
- *card_ptr = G1CardTable::dirty_card_val();
- _dcq.enqueue(card_ptr);
- }
- }
- }
- assert(hrrs.n_yielded() == r->rem_set()->occupied(),
- "Remembered set hash maps out of sync, cur: " SIZE_FORMAT " entries, next: " SIZE_FORMAT " entries",
- hrrs.n_yielded(), r->rem_set()->occupied());
- // We should only clear the card based remembered set here as we will not
- // implicitly rebuild anything else during eager reclaim. Note that at the moment
- // (and probably never) we do not enter this path if there are other kind of
- // remembered sets for this region.
- r->rem_set()->clear_locked(true /* only_cardset */);
- // Clear_locked() above sets the state to Empty. However we want to continue
- // collecting remembered set entries for humongous regions that were not
- // reclaimed.
- r->rem_set()->set_state_complete();
-#ifdef ASSERT
- G1HeapRegionAttr region_attr = g1h->region_attr(oop(r->bottom()));
- assert(region_attr.needs_remset_update(), "must be");
-#endif
- }
- assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty.");
+ // We will later handle the remembered sets of these regions.
} else {
g1h->register_region_with_region_attr(r);
}
@@ -2761,8 +2717,6 @@
size_t total_humongous() const { return _total_humongous; }
size_t candidate_humongous() const { return _candidate_humongous; }
-
- void flush_rem_set_entries() { _dcq.flush(); }
};
void G1CollectedHeap::register_regions_with_region_attr() {
@@ -2775,9 +2729,6 @@
cl.total_humongous(),
cl.candidate_humongous());
_has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
-
- // Finally flush all remembered set entries to re-check into the global DCQS.
- cl.flush_rem_set_entries();
}
#ifndef PRODUCT
@@ -3072,7 +3023,7 @@
workers()->active_workers(),
collection_set()->young_region_length(),
collection_set()->optional_region_length());
- pre_evacuate_collection_set(evacuation_info);
+ pre_evacuate_collection_set(evacuation_info, &per_thread_states);
// Actually do the work...
evacuate_initial_collection_set(&per_thread_states);
@@ -3105,9 +3056,7 @@
double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
- size_t total_cards_scanned = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ScanRSScannedCards) +
- phase_times()->sum_thread_work_items(G1GCPhaseTimes::OptScanRS, G1GCPhaseTimes::ScanRSScannedCards);
- policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc);
+ policy()->record_collection_pause_end(pause_time_ms, heap_used_bytes_before_gc);
}
verify_after_young_collection(verify_type);
@@ -3581,7 +3530,7 @@
phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0);
}
-void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info) {
+void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
_expand_heap_after_alloc_failure = true;
_evacuation_failed = false;
@@ -3592,10 +3541,15 @@
// Initialize the GC alloc regions.
_allocator->init_gc_alloc_regions(evacuation_info);
+ {
+ Ticks start = Ticks::now();
+ rem_set()->prepare_for_scan_heap_roots();
+ phase_times()->record_prepare_heap_roots_time_ms((Ticks::now() - start).seconds() * 1000.0);
+ }
+
register_regions_with_region_attr();
assert(_verifier->check_region_attr_table(), "Inconsistency in the region attributes table.");
- rem_set()->prepare_for_scan_rem_set();
_preserved_marks_set.assert_empty();
#if COMPILER2_OR_JVMCI
@@ -3697,8 +3651,8 @@
void scan_roots(G1ParScanThreadState* pss, uint worker_id) {
_root_processor->evacuate_roots(pss, worker_id);
- _g1h->rem_set()->update_rem_set(pss, worker_id);
- _g1h->rem_set()->scan_rem_set(pss, worker_id, G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ObjCopy, G1GCPhaseTimes::CodeRoots);
+ _g1h->rem_set()->scan_heap_roots(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ObjCopy);
+ _g1h->rem_set()->scan_collection_set_regions(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::CodeRoots, G1GCPhaseTimes::ObjCopy);
}
void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) {
@@ -3725,6 +3679,14 @@
};
void G1CollectedHeap::evacuate_initial_collection_set(G1ParScanThreadStateSet* per_thread_states) {
+ G1GCPhaseTimes* p = phase_times();
+
+ {
+ Ticks start = Ticks::now();
+ rem_set()->merge_heap_roots(false /* remset_only */, G1GCPhaseTimes::MergeRS);
+ p->record_merge_heap_roots_time((Ticks::now() - start).seconds() * 1000.0);
+ }
+
Tickspan task_time;
const uint num_workers = workers()->active_workers();
@@ -3739,7 +3701,6 @@
}
Tickspan total_processing = Ticks::now() - start_processing;
- G1GCPhaseTimes* p = phase_times();
p->record_initial_evac_time(task_time.seconds() * 1000.0);
p->record_or_add_code_root_fixup_time((total_processing - task_time).seconds() * 1000.0);
}
@@ -3747,7 +3708,8 @@
class G1EvacuateOptionalRegionsTask : public G1EvacuateRegionsBaseTask {
void scan_roots(G1ParScanThreadState* pss, uint worker_id) {
- _g1h->rem_set()->scan_rem_set(pss, worker_id, G1GCPhaseTimes::OptScanRS, G1GCPhaseTimes::OptObjCopy, G1GCPhaseTimes::OptCodeRoots);
+ _g1h->rem_set()->scan_heap_roots(pss, worker_id, G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::OptObjCopy);
+ _g1h->rem_set()->scan_collection_set_regions(pss, worker_id, G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::OptCodeRoots, G1GCPhaseTimes::OptObjCopy);
}
void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) {
@@ -3783,8 +3745,6 @@
void G1CollectedHeap::evacuate_optional_collection_set(G1ParScanThreadStateSet* per_thread_states) {
const double gc_start_time_ms = phase_times()->cur_collection_start_sec() * 1000.0;
- Ticks start = Ticks::now();
-
while (!evacuation_failed() && _collection_set.optional_region_length() > 0) {
double time_used_ms = os::elapsedTime() * 1000.0 - gc_start_time_ms;
@@ -3797,18 +3757,24 @@
break;
}
- evacuate_next_optional_regions(per_thread_states);
+ {
+ Ticks start = Ticks::now();
+ rem_set()->merge_heap_roots(true /* remset_only */, G1GCPhaseTimes::OptMergeRS);
+ phase_times()->record_or_add_optional_merge_heap_roots_time((Ticks::now() - start).seconds() * 1000.0);
+ }
+
+ {
+ Ticks start = Ticks::now();
+ evacuate_next_optional_regions(per_thread_states);
+ phase_times()->record_or_add_optional_evac_time((Ticks::now() - start).seconds() * 1000.0);
+ }
}
_collection_set.abandon_optional_collection_set(per_thread_states);
-
- phase_times()->record_or_add_optional_evac_time((Ticks::now() - start).seconds() * 1000.0);
}
void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
- // Also cleans the card table from temporary duplicate detection information used
- // during UpdateRS/ScanRS.
- rem_set()->cleanup_after_scan_rem_set();
+ rem_set()->cleanup_after_scan_heap_roots();
// Process any discovered reference objects - we have
// to do this _before_ we retire the GC alloc regions
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -78,7 +78,6 @@
class G1HotCardCache;
class G1RemSet;
class G1YoungRemSetSamplingThread;
-class HeapRegionRemSetIterator;
class G1ConcurrentMark;
class G1ConcurrentMarkThread;
class G1ConcurrentRefine;
@@ -757,7 +756,7 @@
void evacuate_next_optional_regions(G1ParScanThreadStateSet* per_thread_states);
public:
- void pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info);
+ void pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
void post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
void expand_heap_after_young_collection();
@@ -1115,7 +1114,8 @@
public:
- inline G1HeapRegionAttr region_attr(const void* obj);
+ inline G1HeapRegionAttr region_attr(const void* obj) const;
+ inline G1HeapRegionAttr region_attr(uint idx) const;
// Return "TRUE" iff the given object address is in the reserved
// region of g1.
@@ -1182,7 +1182,12 @@
// Starts the iteration so that the start regions of a given worker id over the
// set active_workers are evenly spread across the set of collection set regions
// to be iterated.
- void collection_set_iterate_increment_from(HeapRegionClosure *blk, uint worker_id);
+ // The variant with the HeapRegionClaimer guarantees that the closure will be
+ // applied to a particular region exactly once.
+ void collection_set_iterate_increment_from(HeapRegionClosure *blk, uint worker_id) {
+ collection_set_iterate_increment_from(blk, NULL, worker_id);
+ }
+ void collection_set_iterate_increment_from(HeapRegionClosure *blk, HeapRegionClaimer* hr_claimer, uint worker_id);
// Returns the HeapRegion that contains addr. addr must not be NULL.
template <class T>
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -163,10 +163,14 @@
return _region_attr.is_in_cset_or_humongous((HeapWord*)obj);
}
-G1HeapRegionAttr G1CollectedHeap::region_attr(const void* addr) {
+G1HeapRegionAttr G1CollectedHeap::region_attr(const void* addr) const {
return _region_attr.at((HeapWord*)addr);
}
+G1HeapRegionAttr G1CollectedHeap::region_attr(uint idx) const {
+ return _region_attr.get_by_index(idx);
+}
+
void G1CollectedHeap::register_humongous_region_with_region_attr(uint index) {
_region_attr.set_humongous(index, region_at(index)->rem_set()->is_tracked());
}
@@ -177,7 +181,7 @@
void G1CollectedHeap::register_old_region_with_region_attr(HeapRegion* r) {
_region_attr.set_in_old(r->hrm_index(), r->rem_set()->is_tracked());
- _rem_set->prepare_for_scan_rem_set(r->hrm_index());
+ _rem_set->prepare_for_scan_heap_roots(r->hrm_index());
}
void G1CollectedHeap::register_optional_region_with_region_attr(HeapRegion* r) {
--- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -217,10 +217,13 @@
}
}
-void G1CollectionSet::iterate_incremental_part_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const {
+void G1CollectionSet::iterate_incremental_part_from(HeapRegionClosure* cl,
+ HeapRegionClaimer* hr_claimer,
+ uint worker_id,
+ uint total_workers) const {
assert_at_safepoint();
- size_t len = _collection_set_cur_length - _inc_part_start;
+ size_t len = increment_length();
if (len == 0) {
return;
}
@@ -229,9 +232,12 @@
size_t cur_pos = start_pos;
do {
- HeapRegion* r = _g1h->region_at(_collection_set_regions[cur_pos + _inc_part_start]);
- bool result = cl->do_heap_region(r);
- guarantee(!result, "Must not cancel iteration");
+ uint region_idx = _collection_set_regions[cur_pos + _inc_part_start];
+ if (hr_claimer == NULL || hr_claimer->claim_region(region_idx)) {
+ HeapRegion* r = _g1h->region_at(region_idx);
+ bool result = cl->do_heap_region(r);
+ guarantee(!result, "Must not cancel iteration");
+ }
cur_pos++;
if (cur_pos == len) {
--- a/src/hotspot/share/gc/g1/g1CollectionSet.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1CollectionSet.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -36,6 +36,7 @@
class G1Policy;
class G1SurvivorRegions;
class HeapRegion;
+class HeapRegionClaimer;
class HeapRegionClosure;
// The collection set.
@@ -279,7 +280,12 @@
// Iterate over the current collection set increment applying the given HeapRegionClosure
// from a starting position determined by the given worker id.
- void iterate_incremental_part_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const;
+ void iterate_incremental_part_from(HeapRegionClosure* cl, HeapRegionClaimer* hr_claimer, uint worker_id, uint total_workers) const;
+
+ // Returns the length of the current increment in number of regions.
+ size_t increment_length() const { return _collection_set_cur_length - _inc_part_start; }
+ // Returns the length of the whole current collection set in number of regions
+ size_t cur_length() const { return _collection_set_cur_length; }
// Iterate over the entire collection set (all increments calculated so far), applying
// the given HeapRegionClosure on all of them.
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -2419,12 +2419,13 @@
abort_marking_if_regular_check_fail();
}
+ // Can't assert qset is empty here, even if not aborted. If concurrent,
+ // some other thread might be adding to the queue. If not concurrent,
+ // some other thread might have won the race for the last buffer, but
+ // has not yet decremented the count.
+
_draining_satb_buffers = false;
- assert(has_aborted() ||
- _cm->concurrent() ||
- satb_mq_set.completed_buffers_num() == 0, "invariant");
-
// again, this was a potentially expensive operation, decrease the
// limits to get the regular clock call early
decrease_limits();
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -206,7 +206,7 @@
// available buffers near green_zone value. When yellow_size is
// large we don't want to allow a full step to accumulate before
// doing any processing, as that might lead to significantly more
- // than green_zone buffers to be processed by update_rs.
+ // than green_zone buffers to be processed during scanning.
step = MIN2(step, ParallelGCThreads / 2.0);
}
size_t activate_offset = static_cast<size_t>(ceil(step * (worker_i + 1)));
@@ -322,18 +322,18 @@
}
static size_t calc_new_green_zone(size_t green,
- double update_rs_time,
- size_t update_rs_processed_buffers,
+ double log_buffer_scan_time,
+ size_t processed_log_buffers,
double goal_ms) {
// Adjust green zone based on whether we're meeting the time goal.
// Limit to max_green_zone.
const double inc_k = 1.1, dec_k = 0.9;
- if (update_rs_time > goal_ms) {
+ if (log_buffer_scan_time > goal_ms) {
if (green > 0) {
green = static_cast<size_t>(green * dec_k);
}
- } else if (update_rs_time < goal_ms &&
- update_rs_processed_buffers > green) {
+ } else if (log_buffer_scan_time < goal_ms &&
+ processed_log_buffers > green) {
green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0));
green = MIN2(green, max_green_zone);
}
@@ -350,20 +350,20 @@
return MIN2(yellow + (yellow - green), max_red_zone);
}
-void G1ConcurrentRefine::update_zones(double update_rs_time,
- size_t update_rs_processed_buffers,
+void G1ConcurrentRefine::update_zones(double log_buffer_scan_time,
+ size_t processed_log_buffers,
double goal_ms) {
log_trace( CTRL_TAGS )("Updating Refinement Zones: "
- "update_rs time: %.3fms, "
- "update_rs buffers: " SIZE_FORMAT ", "
- "update_rs goal time: %.3fms",
- update_rs_time,
- update_rs_processed_buffers,
+ "log buffer scan time: %.3fms, "
+ "processed buffers: " SIZE_FORMAT ", "
+ "goal time: %.3fms",
+ log_buffer_scan_time,
+ processed_log_buffers,
goal_ms);
_green_zone = calc_new_green_zone(_green_zone,
- update_rs_time,
- update_rs_processed_buffers,
+ log_buffer_scan_time,
+ processed_log_buffers,
goal_ms);
_yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size);
_red_zone = calc_new_red_zone(_green_zone, _yellow_zone);
@@ -376,13 +376,13 @@
_green_zone, _yellow_zone, _red_zone);
}
-void G1ConcurrentRefine::adjust(double update_rs_time,
- size_t update_rs_processed_buffers,
+void G1ConcurrentRefine::adjust(double log_buffer_scan_time,
+ size_t processed_log_buffers,
double goal_ms) {
G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
if (G1UseAdaptiveConcRefinement) {
- update_zones(update_rs_time, update_rs_processed_buffers, goal_ms);
+ update_zones(log_buffer_scan_time, processed_log_buffers, goal_ms);
// Change the barrier params
if (max_num_threads() == 0) {
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -97,8 +97,8 @@
size_t min_yellow_zone_size);
// Update green/yellow/red zone values based on how well goals are being met.
- void update_zones(double update_rs_time,
- size_t update_rs_processed_buffers,
+ void update_zones(double log_buffer_scan_time,
+ size_t processed_log_buffers,
double goal_ms);
static uint worker_id_offset();
@@ -115,7 +115,7 @@
void stop();
// Adjust refinement thresholds based on work done during the pause and the goal time.
- void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms);
+ void adjust(double log_buffer_scan_time, size_t processed_log_buffers, double goal_ms);
size_t activation_threshold(uint worker_id) const;
size_t deactivation_threshold(uint worker_id) const;
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -78,7 +78,14 @@
}
G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
- PtrQueueSet(notify_when_complete),
+ PtrQueueSet(),
+ _cbl_mon(NULL),
+ _completed_buffers_head(NULL),
+ _completed_buffers_tail(NULL),
+ _n_completed_buffers(0),
+ _process_completed_buffers_threshold(ProcessCompletedBuffersThresholdNever),
+ _process_completed_buffers(false),
+ _notify_when_complete(notify_when_complete),
_max_completed_buffers(MaxCompletedBuffersUnlimited),
_completed_buffers_padding(0),
_free_ids(NULL),
@@ -90,6 +97,7 @@
}
G1DirtyCardQueueSet::~G1DirtyCardQueueSet() {
+ abandon_completed_buffers();
delete _free_ids;
}
@@ -101,7 +109,9 @@
void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
BufferNode::Allocator* allocator,
bool init_free_ids) {
- PtrQueueSet::initialize(cbl_mon, allocator);
+ PtrQueueSet::initialize(allocator);
+ assert(_cbl_mon == NULL, "Init order issue?");
+ _cbl_mon = cbl_mon;
if (init_free_ids) {
_free_ids = new G1FreeIdSet(0, num_par_ids());
}
@@ -111,6 +121,123 @@
G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
}
+void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ cbn->set_next(NULL);
+ if (_completed_buffers_tail == NULL) {
+ assert(_completed_buffers_head == NULL, "Well-formedness");
+ _completed_buffers_head = cbn;
+ _completed_buffers_tail = cbn;
+ } else {
+ _completed_buffers_tail->set_next(cbn);
+ _completed_buffers_tail = cbn;
+ }
+ _n_completed_buffers++;
+
+ if (!process_completed_buffers() &&
+ (_n_completed_buffers > process_completed_buffers_threshold())) {
+ set_process_completed_buffers(true);
+ if (_notify_when_complete) {
+ _cbl_mon->notify_all();
+ }
+ }
+ assert_completed_buffers_list_len_correct_locked();
+}
+
+BufferNode* G1DirtyCardQueueSet::get_completed_buffer(size_t stop_at) {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+
+ if (_n_completed_buffers <= stop_at) {
+ return NULL;
+ }
+
+ assert(_n_completed_buffers > 0, "invariant");
+ assert(_completed_buffers_head != NULL, "invariant");
+ assert(_completed_buffers_tail != NULL, "invariant");
+
+ BufferNode* bn = _completed_buffers_head;
+ _n_completed_buffers--;
+ _completed_buffers_head = bn->next();
+ if (_completed_buffers_head == NULL) {
+ assert(_n_completed_buffers == 0, "invariant");
+ _completed_buffers_tail = NULL;
+ set_process_completed_buffers(false);
+ }
+ assert_completed_buffers_list_len_correct_locked();
+ bn->set_next(NULL);
+ return bn;
+}
+
+void G1DirtyCardQueueSet::abandon_completed_buffers() {
+ BufferNode* buffers_to_delete = NULL;
+ {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ buffers_to_delete = _completed_buffers_head;
+ _completed_buffers_head = NULL;
+ _completed_buffers_tail = NULL;
+ _n_completed_buffers = 0;
+ set_process_completed_buffers(false);
+ }
+ while (buffers_to_delete != NULL) {
+ BufferNode* bn = buffers_to_delete;
+ buffers_to_delete = bn->next();
+ bn->set_next(NULL);
+ deallocate_buffer(bn);
+ }
+}
+
+void G1DirtyCardQueueSet::notify_if_necessary() {
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ if (_n_completed_buffers > process_completed_buffers_threshold()) {
+ set_process_completed_buffers(true);
+ if (_notify_when_complete)
+ _cbl_mon->notify();
+ }
+}
+
+#ifdef ASSERT
+void G1DirtyCardQueueSet::assert_completed_buffers_list_len_correct_locked() {
+ assert_lock_strong(_cbl_mon);
+ size_t n = 0;
+ for (BufferNode* bn = _completed_buffers_head; bn != NULL; bn = bn->next()) {
+ ++n;
+ }
+ assert(n == _n_completed_buffers,
+ "Completed buffer length is wrong: counted: " SIZE_FORMAT
+ ", expected: " SIZE_FORMAT, n, _n_completed_buffers);
+}
+#endif // ASSERT
+
+// Merge lists of buffers. Notify the processing threads.
+// The source queue is emptied as a result. The queues
+// must share the monitor.
+void G1DirtyCardQueueSet::merge_bufferlists(G1DirtyCardQueueSet *src) {
+ assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
+ MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
+ if (_completed_buffers_tail == NULL) {
+ assert(_completed_buffers_head == NULL, "Well-formedness");
+ _completed_buffers_head = src->_completed_buffers_head;
+ _completed_buffers_tail = src->_completed_buffers_tail;
+ } else {
+ assert(_completed_buffers_head != NULL, "Well formedness");
+ if (src->_completed_buffers_head != NULL) {
+ _completed_buffers_tail->set_next(src->_completed_buffers_head);
+ _completed_buffers_tail = src->_completed_buffers_tail;
+ }
+ }
+ _n_completed_buffers += src->_n_completed_buffers;
+
+ src->_n_completed_buffers = 0;
+ src->_completed_buffers_head = NULL;
+ src->_completed_buffers_tail = NULL;
+ src->set_process_completed_buffers(false);
+
+ assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
+ _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
+ "Sanity");
+ assert_completed_buffers_list_len_correct_locked();
+}
+
bool G1DirtyCardQueueSet::apply_closure_to_buffer(G1CardTableEntryClosure* cl,
BufferNode* node,
bool consume,
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -76,6 +76,21 @@
};
class G1DirtyCardQueueSet: public PtrQueueSet {
+ Monitor* _cbl_mon; // Protects the fields below.
+ BufferNode* _completed_buffers_head;
+ BufferNode* _completed_buffers_tail;
+ volatile size_t _n_completed_buffers;
+
+ size_t _process_completed_buffers_threshold;
+ volatile bool _process_completed_buffers;
+
+ // If true, notify_all on _cbl_mon when the threshold is reached.
+ bool _notify_when_complete;
+
+ void assert_completed_buffers_list_len_correct_locked() NOT_DEBUG_RETURN;
+
+ void abandon_completed_buffers();
+
// Apply the closure to the elements of "node" from it's index to
// buffer_size. If all closure applications return true, then
// returns true. Stops processing after the first closure
@@ -111,7 +126,7 @@
// mutator must start doing some of the concurrent refinement work,
size_t _max_completed_buffers;
size_t _completed_buffers_padding;
- static const size_t MaxCompletedBuffersUnlimited = ~size_t(0);
+ static const size_t MaxCompletedBuffersUnlimited = SIZE_MAX;
G1FreeIdSet* _free_ids;
@@ -142,6 +157,34 @@
// it can be reused in place.
bool process_or_enqueue_completed_buffer(BufferNode* node);
+ virtual void enqueue_completed_buffer(BufferNode* node);
+
+ // If the number of completed buffers is > stop_at, then remove and
+ // return a completed buffer from the list. Otherwise, return NULL.
+ BufferNode* get_completed_buffer(size_t stop_at = 0);
+
+ // The number of buffers in the list. Racy...
+ size_t completed_buffers_num() const { return _n_completed_buffers; }
+
+ bool process_completed_buffers() { return _process_completed_buffers; }
+ void set_process_completed_buffers(bool x) { _process_completed_buffers = x; }
+
+ // Get/Set the number of completed buffers that triggers log processing.
+ // Log processing should be done when the number of buffers exceeds the
+ // threshold.
+ void set_process_completed_buffers_threshold(size_t sz) {
+ _process_completed_buffers_threshold = sz;
+ }
+ size_t process_completed_buffers_threshold() const {
+ return _process_completed_buffers_threshold;
+ }
+ static const size_t ProcessCompletedBuffersThresholdNever = SIZE_MAX;
+
+ // Notify the consumer if the number of buffers crossed the threshold
+ void notify_if_necessary();
+
+ void merge_bufferlists(G1DirtyCardQueueSet* src);
+
// Apply G1RefineCardConcurrentlyClosure to completed buffers until there are stop_at
// completed buffers remaining.
bool refine_completed_buffer_concurrently(uint worker_i, size_t stop_at);
@@ -150,13 +193,13 @@
// must never return false. Must only be called during GC.
bool apply_closure_during_gc(G1CardTableEntryClosure* cl, uint worker_i);
- void reset_for_par_iteration() { _cur_par_buffer_node = completed_buffers_head(); }
+ void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; }
// Applies the current closure to all completed buffers, non-consumptively.
// Can be used in parallel, all callers using the iteration state initialized
// by reset_for_par_iteration.
void par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl);
- // If a full collection is happening, reset partial logs, and ignore
+ // If a full collection is happening, reset partial logs, and release
// completed ones: the full collection will make them all irrelevant.
void abandon_logs();
--- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -37,15 +37,19 @@
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
-class UpdateRSetDeferred : public BasicOopIterateClosure {
+class UpdateLogBuffersDeferred : public BasicOopIterateClosure {
private:
G1CollectedHeap* _g1h;
G1DirtyCardQueue* _dcq;
G1CardTable* _ct;
+ // Remember the last enqueued card to avoid enqueuing the same card over and over;
+ // since we only ever handle a card once, this is sufficient.
+ size_t _last_enqueued_card;
+
public:
- UpdateRSetDeferred(G1DirtyCardQueue* dcq) :
- _g1h(G1CollectedHeap::heap()), _dcq(dcq), _ct(_g1h->card_table()) {}
+ UpdateLogBuffersDeferred(G1DirtyCardQueue* dcq) :
+ _g1h(G1CollectedHeap::heap()), _dcq(dcq), _ct(_g1h->card_table()), _last_enqueued_card(SIZE_MAX) {}
virtual void do_oop(narrowOop* p) { do_oop_work(p); }
virtual void do_oop( oop* p) { do_oop_work(p); }
@@ -62,8 +66,9 @@
return;
}
size_t card_index = _ct->index_for(p);
- if (_ct->mark_card_deferred(card_index)) {
+ if (card_index != _last_enqueued_card) {
_dcq->enqueue(_ct->byte_for_index(card_index));
+ _last_enqueued_card = card_index;
}
}
};
@@ -73,21 +78,21 @@
G1ConcurrentMark* _cm;
HeapRegion* _hr;
size_t _marked_bytes;
- UpdateRSetDeferred* _update_rset_cl;
+ UpdateLogBuffersDeferred* _log_buffer_cl;
bool _during_initial_mark;
uint _worker_id;
HeapWord* _last_forwarded_object_end;
public:
RemoveSelfForwardPtrObjClosure(HeapRegion* hr,
- UpdateRSetDeferred* update_rset_cl,
+ UpdateLogBuffersDeferred* log_buffer_cl,
bool during_initial_mark,
uint worker_id) :
_g1h(G1CollectedHeap::heap()),
_cm(_g1h->concurrent_mark()),
_hr(hr),
_marked_bytes(0),
- _update_rset_cl(update_rset_cl),
+ _log_buffer_cl(log_buffer_cl),
_during_initial_mark(during_initial_mark),
_worker_id(worker_id),
_last_forwarded_object_end(hr->bottom()) { }
@@ -144,7 +149,7 @@
// The problem is that, if evacuation fails, we might have
// remembered set entries missing given that we skipped cards on
// the collection set. So, we'll recreate such entries now.
- obj->oop_iterate(_update_rset_cl);
+ obj->oop_iterate(_log_buffer_cl);
HeapWord* obj_end = obj_addr + obj_size;
_last_forwarded_object_end = obj_end;
@@ -193,25 +198,22 @@
class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h;
uint _worker_id;
- HeapRegionClaimer* _hrclaimer;
G1DirtyCardQueue _dcq;
- UpdateRSetDeferred _update_rset_cl;
+ UpdateLogBuffersDeferred _log_buffer_cl;
public:
- RemoveSelfForwardPtrHRClosure(uint worker_id,
- HeapRegionClaimer* hrclaimer) :
+ RemoveSelfForwardPtrHRClosure(uint worker_id) :
_g1h(G1CollectedHeap::heap()),
_worker_id(worker_id),
- _hrclaimer(hrclaimer),
_dcq(&_g1h->dirty_card_queue_set()),
- _update_rset_cl(&_dcq){
+ _log_buffer_cl(&_dcq) {
}
size_t remove_self_forward_ptr_by_walking_hr(HeapRegion* hr,
bool during_initial_mark) {
RemoveSelfForwardPtrObjClosure rspc(hr,
- &_update_rset_cl,
+ &_log_buffer_cl,
during_initial_mark,
_worker_id);
hr->object_iterate(&rspc);
@@ -225,26 +227,24 @@
assert(!hr->is_pinned(), "Unexpected pinned region at index %u", hr->hrm_index());
assert(hr->in_collection_set(), "bad CS");
- if (_hrclaimer->claim_region(hr->hrm_index())) {
- if (hr->evacuation_failed()) {
- hr->clear_index_in_opt_cset();
+ if (hr->evacuation_failed()) {
+ hr->clear_index_in_opt_cset();
- bool during_initial_mark = _g1h->collector_state()->in_initial_mark_gc();
- bool during_conc_mark = _g1h->collector_state()->mark_or_rebuild_in_progress();
+ bool during_initial_mark = _g1h->collector_state()->in_initial_mark_gc();
+ bool during_conc_mark = _g1h->collector_state()->mark_or_rebuild_in_progress();
- hr->note_self_forwarding_removal_start(during_initial_mark,
+ hr->note_self_forwarding_removal_start(during_initial_mark,
during_conc_mark);
- _g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr);
+ _g1h->verifier()->check_bitmaps("Self-Forwarding Ptr Removal", hr);
- hr->reset_bot();
-
- size_t live_bytes = remove_self_forward_ptr_by_walking_hr(hr, during_initial_mark);
+ hr->reset_bot();
- hr->rem_set()->clean_strong_code_roots(hr);
- hr->rem_set()->clear_locked(true);
+ size_t live_bytes = remove_self_forward_ptr_by_walking_hr(hr, during_initial_mark);
- hr->note_self_forwarding_removal_end(live_bytes);
- }
+ hr->rem_set()->clean_strong_code_roots(hr);
+ hr->rem_set()->clear_locked(true);
+
+ hr->note_self_forwarding_removal_end(live_bytes);
}
return false;
}
@@ -256,7 +256,7 @@
_hrclaimer(_g1h->workers()->active_workers()) { }
void G1ParRemoveSelfForwardPtrsTask::work(uint worker_id) {
- RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id, &_hrclaimer);
+ RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id);
- _g1h->collection_set_iterate_increment_from(&rsfp_cl, worker_id);
+ _g1h->collection_set_iterate_increment_from(&rsfp_cl, &_hrclaimer, worker_id);
}
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -183,7 +183,6 @@
update_derived_pointers();
BiasedLocking::restore_marks();
- JvmtiExport::gc_epilogue();
_heap->prepare_heap_for_mutators();
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -66,14 +66,30 @@
_gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):");
_gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):");
- _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms):");
+ _gc_par_phases[MergeRS] = new WorkerDataArray<double>(max_gc_threads, "Remembered Sets (ms):");
+ _merge_rs_merged_sparse = new WorkerDataArray<size_t>(max_gc_threads, "Merged Sparse:");
+ _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_sparse, MergeRSMergedSparse);
+ _merge_rs_merged_fine = new WorkerDataArray<size_t>(max_gc_threads, "Merged Fine:");
+ _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_fine, MergeRSMergedFine);
+ _merge_rs_merged_coarse = new WorkerDataArray<size_t>(max_gc_threads, "Merged Coarse:");
+ _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_coarse, MergeRSMergedCoarse);
+
+ _gc_par_phases[OptMergeRS] = new WorkerDataArray<double>(max_gc_threads, "Optional Remembered Sets (ms):");
+ _opt_merge_rs_merged_sparse = new WorkerDataArray<size_t>(max_gc_threads, "Merged Sparse:");
+ _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_sparse, MergeRSMergedSparse);
+ _opt_merge_rs_merged_fine = new WorkerDataArray<size_t>(max_gc_threads, "Merged Fine:");
+ _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_fine, MergeRSMergedFine);
+ _opt_merge_rs_merged_coarse = new WorkerDataArray<size_t>(max_gc_threads, "Merged Coarse:");
+ _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_coarse, MergeRSMergedCoarse);
+
+ _gc_par_phases[MergeLB] = new WorkerDataArray<double>(max_gc_threads, "Log Buffers (ms):");
if (G1HotCardCache::default_use_cache()) {
- _gc_par_phases[ScanHCC] = new WorkerDataArray<double>(max_gc_threads, "Scan HCC (ms):");
+ _gc_par_phases[MergeHCC] = new WorkerDataArray<double>(max_gc_threads, "Hot Card Cache (ms):");
} else {
- _gc_par_phases[ScanHCC] = NULL;
+ _gc_par_phases[MergeHCC] = NULL;
}
- _gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms):");
- _gc_par_phases[OptScanRS] = new WorkerDataArray<double>(max_gc_threads, "Optional Scan RS (ms):");
+ _gc_par_phases[ScanHR] = new WorkerDataArray<double>(max_gc_threads, "Scan Heap Roots (ms):");
+ _gc_par_phases[OptScanHR] = new WorkerDataArray<double>(max_gc_threads, "Optional Scan Heap Roots (ms):");
_gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scan (ms):");
_gc_par_phases[OptCodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Optional Code Root Scan (ms):");
_gc_par_phases[ObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Object Copy (ms):");
@@ -84,30 +100,30 @@
_gc_par_phases[GCWorkerEnd] = new WorkerDataArray<double>(max_gc_threads, "GC Worker End (ms):");
_gc_par_phases[Other] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Other (ms):");
- _scan_rs_scanned_cards = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Cards:");
- _gc_par_phases[ScanRS]->link_thread_work_items(_scan_rs_scanned_cards, ScanRSScannedCards);
- _scan_rs_claimed_cards = new WorkerDataArray<size_t>(max_gc_threads, "Claimed Cards:");
- _gc_par_phases[ScanRS]->link_thread_work_items(_scan_rs_claimed_cards, ScanRSClaimedCards);
- _scan_rs_skipped_cards = new WorkerDataArray<size_t>(max_gc_threads, "Skipped Cards:");
- _gc_par_phases[ScanRS]->link_thread_work_items(_scan_rs_skipped_cards, ScanRSSkippedCards);
+ _scan_hr_scanned_cards = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Cards:");
+ _gc_par_phases[ScanHR]->link_thread_work_items(_scan_hr_scanned_cards, ScanHRScannedCards);
+ _scan_hr_scanned_blocks = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Blocks:");
+ _gc_par_phases[ScanHR]->link_thread_work_items(_scan_hr_scanned_blocks, ScanHRScannedBlocks);
+ _scan_hr_claimed_chunks = new WorkerDataArray<size_t>(max_gc_threads, "Claimed Chunks:");
+ _gc_par_phases[ScanHR]->link_thread_work_items(_scan_hr_claimed_chunks, ScanHRClaimedChunks);
- _opt_scan_rs_scanned_cards = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Cards:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_scanned_cards, ScanRSScannedCards);
- _opt_scan_rs_claimed_cards = new WorkerDataArray<size_t>(max_gc_threads, "Claimed Cards:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_claimed_cards, ScanRSClaimedCards);
- _opt_scan_rs_skipped_cards = new WorkerDataArray<size_t>(max_gc_threads, "Skipped Cards:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_skipped_cards, ScanRSSkippedCards);
- _opt_scan_rs_scanned_opt_refs = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Refs:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_scanned_opt_refs, ScanRSScannedOptRefs);
- _opt_scan_rs_used_memory = new WorkerDataArray<size_t>(max_gc_threads, "Used Memory:");
- _gc_par_phases[OptScanRS]->link_thread_work_items(_opt_scan_rs_used_memory, ScanRSUsedMemory);
+ _opt_scan_hr_scanned_cards = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Cards:");
+ _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_scanned_cards, ScanHRScannedCards);
+ _opt_scan_hr_scanned_blocks = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Blocks:");
+ _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_scanned_blocks, ScanHRScannedBlocks);
+ _opt_scan_hr_claimed_chunks = new WorkerDataArray<size_t>(max_gc_threads, "Claimed Chunks:");
+ _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_claimed_chunks, ScanHRClaimedChunks);
+ _opt_scan_hr_scanned_opt_refs = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Refs:");
+ _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_scanned_opt_refs, ScanHRScannedOptRefs);
+ _opt_scan_hr_used_memory = new WorkerDataArray<size_t>(max_gc_threads, "Used Memory:");
+ _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_used_memory, ScanHRUsedMemory);
- _update_rs_processed_buffers = new WorkerDataArray<size_t>(max_gc_threads, "Processed Buffers:");
- _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers, UpdateRSProcessedBuffers);
- _update_rs_scanned_cards = new WorkerDataArray<size_t>(max_gc_threads, "Scanned Cards:");
- _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_scanned_cards, UpdateRSScannedCards);
- _update_rs_skipped_cards = new WorkerDataArray<size_t>(max_gc_threads, "Skipped Cards:");
- _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_skipped_cards, UpdateRSSkippedCards);
+ _merge_lb_processed_buffers = new WorkerDataArray<size_t>(max_gc_threads, "Processed Buffers:");
+ _gc_par_phases[MergeLB]->link_thread_work_items(_merge_lb_processed_buffers, MergeLBProcessedBuffers);
+ _merge_lb_dirty_cards = new WorkerDataArray<size_t>(max_gc_threads, "Dirty Cards:");
+ _gc_par_phases[MergeLB]->link_thread_work_items(_merge_lb_dirty_cards, MergeLBDirtyCards);
+ _merge_lb_skipped_cards = new WorkerDataArray<size_t>(max_gc_threads, "Skipped Cards:");
+ _gc_par_phases[MergeLB]->link_thread_work_items(_merge_lb_skipped_cards, MergeLBSkippedCards);
_obj_copy_lab_waste = new WorkerDataArray<size_t>(max_gc_threads, "LAB Waste");
_gc_par_phases[ObjCopy]->link_thread_work_items(_obj_copy_lab_waste, ObjCopyLABWaste);
@@ -148,6 +164,8 @@
_cur_optional_evac_ms = 0.0;
_cur_collection_code_root_fixup_time_ms = 0.0;
_cur_strong_code_root_purge_time_ms = 0.0;
+ _cur_merge_heap_roots_time_ms = 0.0;
+ _cur_optional_merge_heap_roots_time_ms = 0.0;
_cur_evac_fail_recalc_used = 0.0;
_cur_evac_fail_remove_self_forwards = 0.0;
_cur_string_deduplication_time_ms = 0.0;
@@ -160,6 +178,7 @@
_cur_collection_start_sec = 0.0;
_root_region_scan_wait_time_ms = 0.0;
_external_accounted_time_ms = 0.0;
+ _recorded_prepare_heap_roots_time_ms = 0.0;
_recorded_clear_claimed_marks_time_ms = 0.0;
_recorded_young_cset_choice_time_ms = 0.0;
_recorded_non_young_cset_choice_time_ms = 0.0;
@@ -219,9 +238,7 @@
record_time_secs(GCWorkerTotal, i , total_worker_time);
double worker_known_time = worker_time(ExtRootScan, i) +
- worker_time(ScanHCC, i) +
- worker_time(UpdateRS, i) +
- worker_time(ScanRS, i) +
+ worker_time(ScanHR, i) +
worker_time(CodeRoots, i) +
worker_time(ObjCopy, i) +
worker_time(Termination, i);
@@ -231,11 +248,15 @@
// Make sure all slots are uninitialized since this thread did not seem to have been started
ASSERT_PHASE_UNINITIALIZED(GCWorkerEnd);
ASSERT_PHASE_UNINITIALIZED(ExtRootScan);
- ASSERT_PHASE_UNINITIALIZED(ScanHCC);
- ASSERT_PHASE_UNINITIALIZED(UpdateRS);
- ASSERT_PHASE_UNINITIALIZED(ScanRS);
+ ASSERT_PHASE_UNINITIALIZED(MergeHCC);
+ ASSERT_PHASE_UNINITIALIZED(MergeRS);
+ ASSERT_PHASE_UNINITIALIZED(OptMergeRS);
+ ASSERT_PHASE_UNINITIALIZED(MergeLB);
+ ASSERT_PHASE_UNINITIALIZED(ScanHR);
ASSERT_PHASE_UNINITIALIZED(CodeRoots);
+ ASSERT_PHASE_UNINITIALIZED(OptCodeRoots);
ASSERT_PHASE_UNINITIALIZED(ObjCopy);
+ ASSERT_PHASE_UNINITIALIZED(OptObjCopy);
ASSERT_PHASE_UNINITIALIZED(Termination);
}
}
@@ -365,6 +386,7 @@
_recorded_young_cset_choice_time_ms +
_recorded_non_young_cset_choice_time_ms +
_cur_region_register_time +
+ _recorded_prepare_heap_roots_time_ms +
_recorded_clear_claimed_marks_time_ms;
info_time("Pre Evacuate Collection Set", sum_ms);
@@ -380,6 +402,7 @@
trace_count("Humongous Candidate", _cur_fast_reclaim_humongous_candidates);
}
+ debug_time("Prepare Heap Roots", _recorded_prepare_heap_roots_time_ms);
if (_recorded_clear_claimed_marks_time_ms > 0.0) {
debug_time("Clear Claimed Marks", _recorded_clear_claimed_marks_time_ms);
}
@@ -387,10 +410,13 @@
}
double G1GCPhaseTimes::print_evacuate_optional_collection_set() const {
- const double sum_ms = _cur_optional_evac_ms;
+ const double sum_ms = _cur_optional_evac_ms + _cur_optional_merge_heap_roots_time_ms;
if (sum_ms > 0) {
- info_time("Evacuate Optional Collection Set", sum_ms);
- debug_phase(_gc_par_phases[OptScanRS]);
+ info_time("Merge Optional Heap Roots", _cur_optional_merge_heap_roots_time_ms);
+ debug_phase(_gc_par_phases[OptMergeRS]);
+
+ info_time("Evacuate Optional Collection Set", _cur_optional_evac_ms);
+ debug_phase(_gc_par_phases[OptScanHR]);
debug_phase(_gc_par_phases[OptObjCopy]);
debug_phase(_gc_par_phases[OptCodeRoots]);
debug_phase(_gc_par_phases[OptTermination]);
@@ -398,21 +424,23 @@
return sum_ms;
}
-double G1GCPhaseTimes::print_evacuate_collection_set() const {
- const double sum_ms = _cur_collection_initial_evac_time_ms;
+double G1GCPhaseTimes::print_evacuate_initial_collection_set() const {
+ info_time("Merge Heap Roots", _cur_merge_heap_roots_time_ms);
- info_time("Evacuate Collection Set", sum_ms);
+ debug_phase(_gc_par_phases[MergeRS]);
+ if (G1HotCardCache::default_use_cache()) {
+ debug_phase(_gc_par_phases[MergeHCC]);
+ }
+ debug_phase(_gc_par_phases[MergeLB]);
+
+ info_time("Evacuate Collection Set", _cur_collection_initial_evac_time_ms);
trace_phase(_gc_par_phases[GCWorkerStart], false);
debug_phase(_gc_par_phases[ExtRootScan]);
for (int i = ExtRootScanSubPhasesFirst; i <= ExtRootScanSubPhasesLast; i++) {
trace_phase(_gc_par_phases[i]);
}
- if (G1HotCardCache::default_use_cache()) {
- debug_phase(_gc_par_phases[ScanHCC]);
- }
- debug_phase(_gc_par_phases[UpdateRS]);
- debug_phase(_gc_par_phases[ScanRS]);
+ debug_phase(_gc_par_phases[ScanHR]);
debug_phase(_gc_par_phases[CodeRoots]);
debug_phase(_gc_par_phases[ObjCopy]);
debug_phase(_gc_par_phases[Termination]);
@@ -420,7 +448,7 @@
debug_phase(_gc_par_phases[GCWorkerTotal]);
trace_phase(_gc_par_phases[GCWorkerEnd], false);
- return sum_ms;
+ return _cur_collection_initial_evac_time_ms + _cur_merge_heap_roots_time_ms;
}
double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
@@ -503,7 +531,7 @@
double accounted_ms = 0.0;
accounted_ms += print_pre_evacuate_collection_set();
- accounted_ms += print_evacuate_collection_set();
+ accounted_ms += print_evacuate_initial_collection_set();
accounted_ms += print_evacuate_optional_collection_set();
accounted_ms += print_post_evacuate_collection_set();
print_other(accounted_ms);
@@ -530,10 +558,12 @@
"CMRefRoots",
"WaitForStrongCLD",
"WeakCLDRoots",
- "UpdateRS",
- "ScanHCC",
- "ScanRS",
- "OptScanRS",
+ "MergeRS",
+ "OptMergeRS",
+ "MergeLB",
+ "MergeHCC",
+ "ScanHR",
+ "OptScanHR",
"CodeRoots",
"OptCodeRoots",
"ObjCopy",
@@ -580,8 +610,8 @@
_stopped = true;
}
-G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id) :
- _start_time(), _phase(phase), _phase_times(phase_times), _worker_id(worker_id), _event() {
+G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool must_record) :
+ _start_time(), _phase(phase), _phase_times(phase_times), _worker_id(worker_id), _event(), _must_record(must_record) {
if (_phase_times != NULL) {
_start_time = Ticks::now();
}
@@ -589,7 +619,11 @@
G1GCParPhaseTimesTracker::~G1GCParPhaseTimesTracker() {
if (_phase_times != NULL) {
- _phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds());
+ if (_must_record) {
+ _phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds());
+ } else {
+ _phase_times->record_or_add_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds());
+ }
_event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_phase));
}
}
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -60,10 +60,12 @@
CMRefRoots,
WaitForStrongCLD,
WeakCLDRoots,
- UpdateRS,
- ScanHCC,
- ScanRS,
- OptScanRS,
+ MergeRS,
+ OptMergeRS,
+ MergeLB,
+ MergeHCC,
+ ScanHR,
+ OptScanHR,
CodeRoots,
OptCodeRoots,
ObjCopy,
@@ -84,18 +86,24 @@
static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots;
static const GCParPhases ExtRootScanSubPhasesLast = WeakCLDRoots;
- enum GCScanRSWorkItems {
- ScanRSScannedCards,
- ScanRSClaimedCards,
- ScanRSSkippedCards,
- ScanRSScannedOptRefs,
- ScanRSUsedMemory
+ enum GCMergeRSWorkTimes {
+ MergeRSMergedSparse,
+ MergeRSMergedFine,
+ MergeRSMergedCoarse
};
- enum GCUpdateRSWorkItems {
- UpdateRSProcessedBuffers,
- UpdateRSScannedCards,
- UpdateRSSkippedCards
+ enum GCScanHRWorkItems {
+ ScanHRScannedCards,
+ ScanHRScannedBlocks,
+ ScanHRClaimedChunks,
+ ScanHRScannedOptRefs,
+ ScanHRUsedMemory
+ };
+
+ enum GCMergeLBWorkItems {
+ MergeLBProcessedBuffers,
+ MergeLBDirtyCards,
+ MergeLBSkippedCards
};
enum GCObjCopyWorkItems {
@@ -109,19 +117,27 @@
WorkerDataArray<double>* _gc_par_phases[GCParPhasesSentinel];
- WorkerDataArray<size_t>* _update_rs_processed_buffers;
- WorkerDataArray<size_t>* _update_rs_scanned_cards;
- WorkerDataArray<size_t>* _update_rs_skipped_cards;
+ WorkerDataArray<size_t>* _merge_rs_merged_sparse;
+ WorkerDataArray<size_t>* _merge_rs_merged_fine;
+ WorkerDataArray<size_t>* _merge_rs_merged_coarse;
+
+ WorkerDataArray<size_t>* _merge_lb_processed_buffers;
+ WorkerDataArray<size_t>* _merge_lb_dirty_cards;
+ WorkerDataArray<size_t>* _merge_lb_skipped_cards;
- WorkerDataArray<size_t>* _scan_rs_scanned_cards;
- WorkerDataArray<size_t>* _scan_rs_claimed_cards;
- WorkerDataArray<size_t>* _scan_rs_skipped_cards;
+ WorkerDataArray<size_t>* _scan_hr_scanned_cards;
+ WorkerDataArray<size_t>* _scan_hr_scanned_blocks;
+ WorkerDataArray<size_t>* _scan_hr_claimed_chunks;
- WorkerDataArray<size_t>* _opt_scan_rs_scanned_cards;
- WorkerDataArray<size_t>* _opt_scan_rs_claimed_cards;
- WorkerDataArray<size_t>* _opt_scan_rs_skipped_cards;
- WorkerDataArray<size_t>* _opt_scan_rs_scanned_opt_refs;
- WorkerDataArray<size_t>* _opt_scan_rs_used_memory;
+ WorkerDataArray<size_t>* _opt_merge_rs_merged_sparse;
+ WorkerDataArray<size_t>* _opt_merge_rs_merged_fine;
+ WorkerDataArray<size_t>* _opt_merge_rs_merged_coarse;
+
+ WorkerDataArray<size_t>* _opt_scan_hr_scanned_cards;
+ WorkerDataArray<size_t>* _opt_scan_hr_scanned_blocks;
+ WorkerDataArray<size_t>* _opt_scan_hr_claimed_chunks;
+ WorkerDataArray<size_t>* _opt_scan_hr_scanned_opt_refs;
+ WorkerDataArray<size_t>* _opt_scan_hr_used_memory;
WorkerDataArray<size_t>* _obj_copy_lab_waste;
WorkerDataArray<size_t>* _obj_copy_lab_undo_waste;
@@ -145,6 +161,9 @@
double _cur_string_deduplication_time_ms;
+ double _cur_merge_heap_roots_time_ms;
+ double _cur_optional_merge_heap_roots_time_ms;
+
double _cur_prepare_tlab_time_ms;
double _cur_resize_tlab_time_ms;
@@ -159,6 +178,8 @@
double _external_accounted_time_ms;
+ double _recorded_prepare_heap_roots_time_ms;
+
double _recorded_clear_claimed_marks_time_ms;
double _recorded_young_cset_choice_time_ms;
@@ -208,7 +229,8 @@
void trace_count(const char* name, size_t value) const;
double print_pre_evacuate_collection_set() const;
- double print_evacuate_collection_set() const;
+ double print_merge_heap_roots_time() const;
+ double print_evacuate_initial_collection_set() const;
double print_evacuate_optional_collection_set() const;
double print_post_evacuate_collection_set() const;
void print_other(double accounted_ms) const;
@@ -278,6 +300,14 @@
_cur_strong_code_root_purge_time_ms = ms;
}
+ void record_merge_heap_roots_time(double ms) {
+ _cur_merge_heap_roots_time_ms += ms;
+ }
+
+ void record_or_add_optional_merge_heap_roots_time(double ms) {
+ _cur_optional_merge_heap_roots_time_ms += ms;
+ }
+
void record_evac_fail_recalc_used_time(double ms) {
_cur_evac_fail_recalc_used = ms;
}
@@ -357,6 +387,10 @@
_external_accounted_time_ms += time_ms;
}
+ void record_prepare_heap_roots_time_ms(double recorded_prepare_heap_roots_time_ms) {
+ _recorded_prepare_heap_roots_time_ms = recorded_prepare_heap_roots_time_ms;
+ }
+
void record_clear_claimed_marks_time_ms(double recorded_clear_claimed_marks_time_ms) {
_recorded_clear_claimed_marks_time_ms = recorded_clear_claimed_marks_time_ms;
}
@@ -397,6 +431,10 @@
return _cur_fast_reclaim_humongous_time_ms;
}
+ size_t fast_reclaim_humongous_candidates() const {
+ return _cur_fast_reclaim_humongous_candidates;
+ }
+
ReferenceProcessorPhaseTimes* ref_phase_times() { return &_ref_phase_times; }
WeakProcessorPhaseTimes* weak_phase_times() { return &_weak_phase_times; }
@@ -424,8 +462,10 @@
G1GCPhaseTimes* _phase_times;
uint _worker_id;
EventGCPhaseParallel _event;
+ bool _must_record;
+
public:
- G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id);
+ G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool must_record = true);
virtual ~G1GCParPhaseTimesTracker();
};
--- a/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -39,8 +39,8 @@
}
// After a collection pause, young list target length is updated. So we need to make sure we have enough regions in dram for young gen.
-void G1HeterogeneousHeapPolicy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc) {
- G1Policy::record_collection_pause_end(pause_time_ms, cards_scanned, heap_used_bytes_before_gc);
+void G1HeterogeneousHeapPolicy::record_collection_pause_end(double pause_time_ms, size_t heap_used_bytes_before_gc) {
+ G1Policy::record_collection_pause_end(pause_time_ms, heap_used_bytes_before_gc);
_manager->adjust_dram_regions((uint)young_list_target_length(), G1CollectedHeap::heap()->workers());
}
--- a/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1HeterogeneousHeapPolicy.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -38,7 +38,7 @@
// initialize policy
virtual void init(G1CollectedHeap* g1h, G1CollectionSet* collection_set);
// Record end of an evacuation pause.
- virtual void record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc);
+ virtual void record_collection_pause_end(double pause_time_ms, size_t heap_used_bytes_before_gc);
// Record the end of full collection.
virtual void record_full_collection_end();
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -51,6 +51,7 @@
_tenuring_threshold(g1h->policy()->tenuring_threshold()),
_scanner(g1h, this),
_worker_id(worker_id),
+ _last_enqueued_card(SIZE_MAX),
_stack_trim_upper_threshold(GCDrainStackTargetSize * 2 + 1),
_stack_trim_lower_threshold(GCDrainStackTargetSize),
_trim_ticks(),
@@ -371,7 +372,7 @@
}
size_t used_memory = pss->oops_into_optional_region(hr)->used_memory();
- _g1h->phase_times()->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanRS, worker_index, used_memory, G1GCPhaseTimes::ScanRSUsedMemory);
+ _g1h->phase_times()->record_or_add_thread_work_item(G1GCPhaseTimes::OptScanHR, worker_index, used_memory, G1GCPhaseTimes::ScanHRUsedMemory);
}
}
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -60,6 +60,10 @@
uint _worker_id;
+ // Remember the last enqueued card to avoid enqueuing the same card over and over;
+ // since we only ever scan a card once, this is sufficient.
+ size_t _last_enqueued_card;
+
// Upper and lower threshold to start and end work queue draining.
uint const _stack_trim_upper_threshold;
uint const _stack_trim_lower_threshold;
@@ -128,8 +132,9 @@
}
size_t card_index = ct()->index_for(p);
// If the card hasn't been added to the buffer, do it.
- if (ct()->mark_card_deferred(card_index)) {
+ if (_last_enqueued_card != card_index) {
dirty_card_queue().enqueue(ct()->byte_for_index(card_index));
+ _last_enqueued_card = card_index;
}
}
--- a/src/hotspot/share/gc/g1/g1Policy.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -572,10 +572,24 @@
return result;
}
+double G1Policy::log_buffer_processing_time() const {
+ double all_cards_processing_time = average_time_ms(G1GCPhaseTimes::ScanHR) + average_time_ms(G1GCPhaseTimes::OptScanHR);
+ size_t log_buffer_dirty_cards = phase_times()->sum_thread_work_items(G1GCPhaseTimes::MergeLB, G1GCPhaseTimes::MergeLBDirtyCards);
+ size_t scan_heap_roots_cards = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ScanHRScannedCards) +
+ phase_times()->sum_thread_work_items(G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::ScanHRScannedCards);
+ // This may happen if there are duplicate cards in different log buffers.
+ if (log_buffer_dirty_cards > scan_heap_roots_cards) {
+ return all_cards_processing_time + average_time_ms(G1GCPhaseTimes::MergeLB);
+ }
+ return (all_cards_processing_time * log_buffer_dirty_cards / scan_heap_roots_cards) + average_time_ms(G1GCPhaseTimes::MergeLB);
+}
+
// Anything below that is considered to be zero
#define MIN_TIMER_GRANULARITY 0.0000001
-void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc) {
+void G1Policy::record_collection_pause_end(double pause_time_ms, size_t heap_used_bytes_before_gc) {
+ G1GCPhaseTimes* p = phase_times();
+
double end_time_sec = os::elapsedTime();
assert_used_and_recalculate_used_equal(_g1h);
@@ -645,29 +659,40 @@
_short_lived_surv_rate_group->start_adding_regions();
// Do that for any other surv rate groups
- double scan_hcc_time_ms = G1HotCardCache::default_use_cache() ? average_time_ms(G1GCPhaseTimes::ScanHCC) : 0.0;
+ double scan_hcc_time_ms = G1HotCardCache::default_use_cache() ? average_time_ms(G1GCPhaseTimes::MergeHCC) : 0.0;
if (update_stats) {
- double cost_per_card_ms = 0.0;
- if (_pending_cards > 0) {
- cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS)) / (double) _pending_cards;
- _analytics->report_cost_per_card_ms(cost_per_card_ms);
+ double cost_per_log_buffer_entry = 0.0;
+ size_t const pending_log_buffer_entries = p->sum_thread_work_items(G1GCPhaseTimes::MergeLB, G1GCPhaseTimes::MergeLBDirtyCards);
+ if (pending_log_buffer_entries > 0) {
+ cost_per_log_buffer_entry = log_buffer_processing_time() / pending_log_buffer_entries;
+ _analytics->report_cost_per_log_buffer_entry_ms(cost_per_log_buffer_entry);
}
_analytics->report_cost_scan_hcc(scan_hcc_time_ms);
- double cost_per_entry_ms = 0.0;
- if (cards_scanned > 10) {
- double avg_time_scan_rs = average_time_ms(G1GCPhaseTimes::ScanRS);
- if (this_pause_was_young_only) {
- avg_time_scan_rs += average_time_ms(G1GCPhaseTimes::OptScanRS);
- }
- cost_per_entry_ms = avg_time_scan_rs / cards_scanned;
- _analytics->report_cost_per_entry_ms(cost_per_entry_ms, this_pause_was_young_only);
+ size_t const total_cards_scanned = p->sum_thread_work_items(G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ScanHRScannedCards) +
+ p->sum_thread_work_items(G1GCPhaseTimes::OptScanHR, G1GCPhaseTimes::ScanHRScannedCards);
+ size_t remset_cards_scanned = 0;
+ // There might have been duplicate log buffer entries in the queues which could
+ // increase this value beyond the cards scanned. In this case attribute all cards
+ // to the log buffers.
+ if (pending_log_buffer_entries <= total_cards_scanned) {
+ remset_cards_scanned = total_cards_scanned - pending_log_buffer_entries;
+ }
+
+ double cost_per_remset_card_ms = 0.0;
+ if (remset_cards_scanned > 10) {
+ double avg_time_remset_scan = ((average_time_ms(G1GCPhaseTimes::ScanHR) + average_time_ms(G1GCPhaseTimes::OptScanHR)) *
+ remset_cards_scanned / total_cards_scanned) +
+ average_time_ms(G1GCPhaseTimes::MergeRS);
+
+ cost_per_remset_card_ms = avg_time_remset_scan / remset_cards_scanned;
+ _analytics->report_cost_per_remset_card_ms(cost_per_remset_card_ms, this_pause_was_young_only);
}
if (_max_rs_lengths > 0) {
double cards_per_entry_ratio =
- (double) cards_scanned / (double) _max_rs_lengths;
+ (double) remset_cards_scanned / (double) _max_rs_lengths;
_analytics->report_cards_per_entry_ratio(cards_per_entry_ratio, this_pause_was_young_only);
}
@@ -759,20 +784,26 @@
}
// 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_log_buffer_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
- if (update_rs_time_goal_ms < scan_hcc_time_ms) {
+ if (scan_log_buffer_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",
- update_rs_time_goal_ms, scan_hcc_time_ms);
+ "Log Buffer Scan time goal: %1.2fms Scan HCC time: %1.2fms",
+ scan_log_buffer_time_goal_ms, scan_hcc_time_ms);
- update_rs_time_goal_ms = 0;
+ scan_log_buffer_time_goal_ms = 0;
} else {
- update_rs_time_goal_ms -= scan_hcc_time_ms;
+ scan_log_buffer_time_goal_ms -= scan_hcc_time_ms;
}
- _g1h->concurrent_refine()->adjust(average_time_ms(G1GCPhaseTimes::UpdateRS),
- phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
- update_rs_time_goal_ms);
+
+ double const log_buffer_time = log_buffer_processing_time();
+
+ log_debug(gc, ergo, refine)("Concurrent refinement times: Log Buffer Scan time goal: %1.2fms Log Buffer Scan time: %1.2fms HCC time: %1.2fms",
+ scan_log_buffer_time_goal_ms, log_buffer_time, scan_hcc_time_ms);
+
+ _g1h->concurrent_refine()->adjust(log_buffer_time,
+ phase_times()->sum_thread_work_items(G1GCPhaseTimes::MergeLB, G1GCPhaseTimes::MergeLBProcessedBuffers),
+ scan_log_buffer_time_goal_ms);
}
G1IHOPControl* G1Policy::create_ihop_control(const G1Predictions* predictor){
--- a/src/hotspot/share/gc/g1/g1Policy.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -111,6 +111,8 @@
bool should_update_surv_rate_group_predictors() {
return collector_state()->in_young_only_phase() && !collector_state()->mark_or_rebuild_in_progress();
}
+
+ double log_buffer_processing_time() const;
public:
const G1Predictions& predictor() const { return _predictor; }
const G1Analytics* analytics() const { return const_cast<const G1Analytics*>(_analytics); }
@@ -311,7 +313,7 @@
// Record the start and end of an evacuation pause.
void record_collection_pause_start(double start_time_sec);
- virtual void record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc);
+ virtual void record_collection_pause_end(double pause_time_ms, size_t heap_used_bytes_before_gc);
// Record the start and end of a full collection.
void record_full_collection_start();
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -38,7 +38,8 @@
#include "gc/g1/g1SharedDirtyCardQueue.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
-#include "gc/g1/heapRegionRemSet.hpp"
+#include "gc/g1/heapRegionRemSet.inline.hpp"
+#include "gc/g1/sparsePRT.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/suspendibleThreadSet.hpp"
#include "jfr/jfrEvents.hpp"
@@ -52,40 +53,453 @@
#include "utilities/stack.inline.hpp"
#include "utilities/ticks.hpp"
-// Collects information about the overall remembered set scan progress during an evacuation.
+// Collects information about the overall heap root scan progress during an evacuation.
+//
+// Scanning the remembered sets works by first merging all sources of cards to be
+// scanned (log buffers, hcc, remembered sets) into a single data structure to remove
+// duplicates and simplify work distribution.
+//
+// During the following card scanning we not only scan this combined set of cards, but
+// also remember that these were completely scanned. The following evacuation passes
+// do not scan these cards again, and so need to be preserved across increments.
+//
+// The representation for all the cards to scan is the card table: cards can have
+// one of three states during GC:
+// - clean: these cards will not be scanned in this pass
+// - dirty: these cards will be scanned in this pass
+// - scanned: these cards have already been scanned in a previous pass
+//
+// After all evacuation is done, we reset the card table to clean.
+//
+// Work distribution occurs on "chunk" basis, i.e. contiguous ranges of cards. As an
+// additional optimization, during card merging we remember which regions and which
+// chunks actually contain cards to be scanned. Threads iterate only across these
+// regions, and only compete for chunks containing any cards.
+//
+// Within these chunks, a worker scans the card table on "blocks" of cards, i.e.
+// contiguous ranges of dirty cards to be scanned. These blocks are converted to actual
+// memory ranges and then passed on to actual scanning.
class G1RemSetScanState : public CHeapObj<mtGC> {
+ class G1DirtyRegions;
+
+ size_t _max_regions;
+
+ // Has this region that is part of the regions in the collection set been processed yet.
+ typedef bool G1RemsetIterState;
+
+ G1RemsetIterState volatile* _collection_set_iter_state;
+
+ // Card table iteration claim for each heap region, from 0 (completely unscanned)
+ // to (>=) HeapRegion::CardsPerRegion (completely scanned).
+ uint volatile* _card_table_scan_state;
+
+ // Random power of two number of cards we want to claim per thread. This corresponds
+ // to a 64k of memory work chunk area for every thread.
+ // We use the same claim size as Parallel GC. No particular measurements have been
+ // performed to determine an optimal number.
+ static const uint CardsPerChunk = 128;
+
+ uint _scan_chunks_per_region;
+ bool* _region_scan_chunks;
+ uint8_t _scan_chunks_shift;
+public:
+ uint scan_chunk_size() const { return (uint)1 << _scan_chunks_shift; }
+
+ // Returns whether the chunk corresponding to the given region/card in region contain a
+ // dirty card, i.e. actually needs scanning.
+ bool chunk_needs_scan(uint const region_idx, uint const card_in_region) const {
+ size_t const idx = (size_t)region_idx * _scan_chunks_per_region + (card_in_region >> _scan_chunks_shift);
+ assert(idx < (_max_regions * _scan_chunks_per_region), "Index " SIZE_FORMAT " out of bounds " SIZE_FORMAT,
+ idx, _max_regions * _scan_chunks_per_region);
+ return _region_scan_chunks[idx];
+ }
+
private:
+ // The complete set of regions which card table needs to be cleared at the end of GC because
+ // we scribbled all over them.
+ G1DirtyRegions* _all_dirty_regions;
+ // The set of regions which card table needs to be scanned for new dirty cards
+ // in the current evacuation pass.
+ G1DirtyRegions* _next_dirty_regions;
+
+ // Set of (unique) regions that can be added to concurrently.
+ class G1DirtyRegions : public CHeapObj<mtGC> {
+ uint* _buffer;
+ uint _cur_idx;
+ size_t _max_regions;
+
+ bool* _contains;
+
+ public:
+ G1DirtyRegions(size_t max_regions) :
+ _buffer(NEW_C_HEAP_ARRAY(uint, max_regions, mtGC)),
+ _cur_idx(0),
+ _max_regions(max_regions),
+ _contains(NEW_C_HEAP_ARRAY(bool, max_regions, mtGC)) {
+
+ reset();
+ }
+
+ static size_t chunk_size() { return M; }
+
+ ~G1DirtyRegions() {
+ FREE_C_HEAP_ARRAY(uint, _buffer);
+ FREE_C_HEAP_ARRAY(bool, _contains);
+ }
+
+ void reset() {
+ _cur_idx = 0;
+ ::memset(_contains, false, _max_regions * sizeof(bool));
+ }
+
+ uint size() const { return _cur_idx; }
+
+ uint at(uint idx) const {
+ assert(idx < _cur_idx, "Index %u beyond valid regions", idx);
+ return _buffer[idx];
+ }
+
+ void add_dirty_region(uint region) {
+ if (_contains[region]) {
+ return;
+ }
+
+ bool marked_as_dirty = Atomic::cmpxchg(true, &_contains[region], false) == false;
+ if (marked_as_dirty) {
+ uint allocated = Atomic::add(1u, &_cur_idx) - 1;
+ _buffer[allocated] = region;
+ }
+ }
+
+ // Creates the union of this and the other G1DirtyRegions.
+ void merge(const G1DirtyRegions* other) {
+ for (uint i = 0; i < other->size(); i++) {
+ uint region = other->at(i);
+ if (!_contains[region]) {
+ _buffer[_cur_idx++] = region;
+ _contains[region] = true;
+ }
+ }
+ }
+ };
+
+ // Returns whether the given region contains cards we need to scan. The remembered
+ // set and other sources may contain cards that
+ // - are in uncommitted regions
+ // - are located in the collection set
+ // - are located in free regions
+ // as we do not clean up remembered sets before merging heap roots.
+ bool contains_cards_to_process(uint const region_idx) const {
+ HeapRegion* hr = G1CollectedHeap::heap()->region_at_or_null(region_idx);
+ return (hr != NULL && !hr->in_collection_set() && hr->is_old_or_humongous_or_archive());
+ }
+
+ class G1MergeCardSetClosure : public HeapRegionClosure {
+ G1RemSetScanState* _scan_state;
+ G1CardTable* _ct;
+
+ uint _merged_sparse;
+ uint _merged_fine;
+ uint _merged_coarse;
+
+ // Returns if the region contains cards we need to scan. If so, remember that
+ // region in the current set of dirty regions.
+ bool remember_if_interesting(uint const region_idx) {
+ if (!_scan_state->contains_cards_to_process(region_idx)) {
+ return false;
+ }
+ _scan_state->add_dirty_region(region_idx);
+ return true;
+ }
+ public:
+ G1MergeCardSetClosure(G1RemSetScanState* scan_state) :
+ _scan_state(scan_state),
+ _ct(G1CollectedHeap::heap()->card_table()),
+ _merged_sparse(0),
+ _merged_fine(0),
+ _merged_coarse(0) { }
+
+ void next_coarse_prt(uint const region_idx) {
+ if (!remember_if_interesting(region_idx)) {
+ return;
+ }
+
+ _merged_coarse++;
+
+ size_t region_base_idx = (size_t)region_idx << HeapRegion::LogCardsPerRegion;
+ _ct->mark_region_dirty(region_base_idx, HeapRegion::CardsPerRegion);
+ _scan_state->set_chunk_region_dirty(region_base_idx);
+ }
+
+ void next_fine_prt(uint const region_idx, BitMap* bm) {
+ if (!remember_if_interesting(region_idx)) {
+ return;
+ }
+
+ _merged_fine++;
+
+ size_t const region_base_idx = (size_t)region_idx << HeapRegion::LogCardsPerRegion;
+ BitMap::idx_t cur = bm->get_next_one_offset(0);
+ while (cur != bm->size()) {
+ _ct->mark_clean_as_dirty(region_base_idx + cur);
+ _scan_state->set_chunk_dirty(region_base_idx + cur);
+ cur = bm->get_next_one_offset(cur + 1);
+ }
+ }
+
+ void next_sparse_prt(uint const region_idx, SparsePRTEntry::card_elem_t* cards, uint const num_cards) {
+ if (!remember_if_interesting(region_idx)) {
+ return;
+ }
+
+ _merged_sparse++;
+
+ size_t const region_base_idx = (size_t)region_idx << HeapRegion::LogCardsPerRegion;
+ for (uint i = 0; i < num_cards; i++) {
+ size_t card_idx = region_base_idx + cards[i];
+ _ct->mark_clean_as_dirty(card_idx);
+ _scan_state->set_chunk_dirty(card_idx);
+ }
+ }
+
+ virtual bool do_heap_region(HeapRegion* r) {
+ assert(r->in_collection_set() || r->is_starts_humongous(), "must be");
+
+ HeapRegionRemSet* rem_set = r->rem_set();
+ if (!rem_set->is_empty()) {
+ rem_set->iterate_prts(*this);
+ }
+
+ return false;
+ }
+
+ size_t merged_sparse() const { return _merged_sparse; }
+ size_t merged_fine() const { return _merged_fine; }
+ size_t merged_coarse() const { return _merged_coarse; }
+ };
+
+ // Visitor for the remembered sets of humongous candidate regions to merge their
+ // remembered set into the card table.
+ class G1FlushHumongousCandidateRemSets : public HeapRegionClosure {
+ G1MergeCardSetClosure _cl;
+
+ public:
+ G1FlushHumongousCandidateRemSets(G1RemSetScanState* scan_state) : _cl(scan_state) { }
+
+ virtual bool do_heap_region(HeapRegion* r) {
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+ if (!r->is_starts_humongous() ||
+ !g1h->region_attr(r->hrm_index()).is_humongous() ||
+ r->rem_set()->is_empty()) {
+ return false;
+ }
+
+ guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries),
+ "Found a not-small remembered set here. This is inconsistent with previous assumptions.");
+
+ _cl.do_heap_region(r);
+
+ // We should only clear the card based remembered set here as we will not
+ // implicitly rebuild anything else during eager reclaim. Note that at the moment
+ // (and probably never) we do not enter this path if there are other kind of
+ // remembered sets for this region.
+ r->rem_set()->clear_locked(true /* only_cardset */);
+ // Clear_locked() above sets the state to Empty. However we want to continue
+ // collecting remembered set entries for humongous regions that were not
+ // reclaimed.
+ r->rem_set()->set_state_complete();
+#ifdef ASSERT
+ G1HeapRegionAttr region_attr = g1h->region_attr(r->hrm_index());
+ assert(region_attr.needs_remset_update(), "must be");
+#endif
+ assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty.");
+
+ return false;
+ }
+
+ size_t merged_sparse() const { return _cl.merged_sparse(); }
+ size_t merged_fine() const { return _cl.merged_fine(); }
+ size_t merged_coarse() const { return _cl.merged_coarse(); }
+ };
+
+ // Visitor for the log buffer entries to merge them into the card table.
+ class G1MergeLogBufferCardsClosure : public G1CardTableEntryClosure {
+ G1RemSetScanState* _scan_state;
+ G1CardTable* _ct;
+
+ size_t _cards_dirty;
+ size_t _cards_skipped;
+ public:
+ G1MergeLogBufferCardsClosure(G1CollectedHeap* g1h, G1RemSetScanState* scan_state) :
+ _scan_state(scan_state), _ct(g1h->card_table()), _cards_dirty(0), _cards_skipped(0)
+ {}
+
+ bool do_card_ptr(CardValue* card_ptr, uint worker_i) {
+ // The only time we care about recording cards that
+ // contain references that point into the collection set
+ // is during RSet updating within an evacuation pause.
+ // In this case worker_id should be the id of a GC worker thread.
+ assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
+
+ uint const region_idx = _ct->region_idx_for(card_ptr);
+
+ // The second clause must come after - the log buffers might contain cards to uncommited
+ // regions.
+ // This code may count duplicate entries in the log buffers (even if rare) multiple
+ // times.
+ if (_scan_state->contains_cards_to_process(region_idx) && (*card_ptr == G1CardTable::dirty_card_val())) {
+ _scan_state->add_dirty_region(region_idx);
+ _scan_state->set_chunk_dirty(_ct->index_for_cardvalue(card_ptr));
+ _cards_dirty++;
+ } else {
+ // We may have had dirty cards in the (initial) collection set (or the
+ // young regions which are always in the initial collection set). We do
+ // not fix their cards here: we already added these regions to the set of
+ // regions to clear the card table at the end during the prepare() phase.
+ _cards_skipped++;
+ }
+ return true;
+ }
+
+ size_t cards_dirty() const { return _cards_dirty; }
+ size_t cards_skipped() const { return _cards_skipped; }
+ };
+
+ class G1MergeHeapRootsTask : public AbstractGangTask {
+ HeapRegionClaimer _hr_claimer;
+ G1RemSetScanState* _scan_state;
+ bool _remembered_set_only;
+
+ G1GCPhaseTimes::GCParPhases _merge_phase;
+
+ volatile bool _fast_reclaim_handled;
+
+ public:
+ G1MergeHeapRootsTask(G1RemSetScanState* scan_state, uint num_workers, bool remembered_set_only, G1GCPhaseTimes::GCParPhases merge_phase) :
+ AbstractGangTask("G1 Merge Heap Roots"),
+ _hr_claimer(num_workers),
+ _scan_state(scan_state),
+ _remembered_set_only(remembered_set_only),
+ _merge_phase(merge_phase),
+ _fast_reclaim_handled(false) { }
+
+ virtual void work(uint worker_id) {
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ G1GCPhaseTimes* p = g1h->phase_times();
+
+ // We schedule flushing the remembered sets of humongous fast reclaim candidates
+ // onto the card table first to allow the remaining parallelized tasks hide it.
+ if (!_remembered_set_only &&
+ p->fast_reclaim_humongous_candidates() > 0 &&
+ !_fast_reclaim_handled &&
+ !Atomic::cmpxchg(true, &_fast_reclaim_handled, false)) {
+
+ G1FlushHumongousCandidateRemSets cl(_scan_state);
+ g1h->heap_region_iterate(&cl);
+
+ p->record_or_add_thread_work_item(_merge_phase, worker_id, cl.merged_sparse(), G1GCPhaseTimes::MergeRSMergedSparse);
+ p->record_or_add_thread_work_item(_merge_phase, worker_id, cl.merged_fine(), G1GCPhaseTimes::MergeRSMergedFine);
+ p->record_or_add_thread_work_item(_merge_phase, worker_id, cl.merged_coarse(), G1GCPhaseTimes::MergeRSMergedCoarse);
+ }
+
+ // Merge remembered sets of current candidates.
+ {
+ G1GCParPhaseTimesTracker x(p, _merge_phase, worker_id, !_remembered_set_only /* must_record */);
+ G1MergeCardSetClosure cl(_scan_state);
+ g1h->collection_set_iterate_increment_from(&cl, &_hr_claimer, worker_id);
+
+ p->record_or_add_thread_work_item(_merge_phase, worker_id, cl.merged_sparse(), G1GCPhaseTimes::MergeRSMergedSparse);
+ p->record_or_add_thread_work_item(_merge_phase, worker_id, cl.merged_fine(), G1GCPhaseTimes::MergeRSMergedFine);
+ p->record_or_add_thread_work_item(_merge_phase, worker_id, cl.merged_coarse(), G1GCPhaseTimes::MergeRSMergedCoarse);
+ }
+
+ // Apply closure to log entries in the HCC.
+ if (!_remembered_set_only && G1HotCardCache::default_use_cache()) {
+ assert(_merge_phase == G1GCPhaseTimes::MergeRS, "Wrong merge phase");
+ G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::MergeHCC, worker_id);
+ G1MergeLogBufferCardsClosure cl(g1h, _scan_state);
+ g1h->iterate_hcc_closure(&cl, worker_id);
+ }
+
+ // Now apply the closure to all remaining log entries.
+ if (!_remembered_set_only) {
+ assert(_merge_phase == G1GCPhaseTimes::MergeRS, "Wrong merge phase");
+ G1GCParPhaseTimesTracker x(p, G1GCPhaseTimes::MergeLB, worker_id);
+
+ G1MergeLogBufferCardsClosure cl(g1h, _scan_state);
+ g1h->iterate_dirty_card_closure(&cl, worker_id);
+
+ p->record_thread_work_item(G1GCPhaseTimes::MergeLB, worker_id, cl.cards_dirty(), G1GCPhaseTimes::MergeLBDirtyCards);
+ p->record_thread_work_item(G1GCPhaseTimes::MergeLB, worker_id, cl.cards_skipped(), G1GCPhaseTimes::MergeLBSkippedCards);
+ }
+ }
+ };
+
+ // Creates a snapshot of the current _top values at the start of collection to
+ // filter out card marks that we do not want to scan.
+ class G1ResetScanTopClosure : public HeapRegionClosure {
+ G1RemSetScanState* _scan_state;
+
+ public:
+ G1ResetScanTopClosure(G1RemSetScanState* scan_state) : _scan_state(scan_state) { }
+
+ virtual bool do_heap_region(HeapRegion* r) {
+ uint hrm_index = r->hrm_index();
+ if (r->in_collection_set()) {
+ // Young regions had their card table marked as young at their allocation;
+ // we need to make sure that these marks are cleared at the end of GC, *but*
+ // they should not be scanned for cards.
+ // So directly add them to the "all_dirty_regions".
+ // Same for regions in the (initial) collection set: they may contain cards from
+ // the log buffers, make sure they are cleaned.
+ _scan_state->add_all_dirty_region(hrm_index);
+ } else if (r->is_old_or_humongous_or_archive()) {
+ _scan_state->set_scan_top(hrm_index, r->top());
+ }
+ return false;
+ }
+ };
+ // For each region, contains the maximum top() value to be used during this garbage
+ // collection. Subsumes common checks like filtering out everything but old and
+ // humongous regions outside the collection set.
+ // This is valid because we are not interested in scanning stray remembered set
+ // entries from free or archive regions.
+ HeapWord** _scan_top;
+
class G1ClearCardTableTask : public AbstractGangTask {
G1CollectedHeap* _g1h;
- uint* _dirty_region_list;
- size_t _num_dirty_regions;
- size_t _chunk_length;
+ G1DirtyRegions* _regions;
+ uint _chunk_length;
- size_t volatile _cur_dirty_regions;
+ uint volatile _cur_dirty_regions;
+
+ G1RemSetScanState* _scan_state;
+
public:
G1ClearCardTableTask(G1CollectedHeap* g1h,
- uint* dirty_region_list,
- size_t num_dirty_regions,
- size_t chunk_length) :
+ G1DirtyRegions* regions,
+ uint chunk_length,
+ G1RemSetScanState* scan_state) :
AbstractGangTask("G1 Clear Card Table Task"),
_g1h(g1h),
- _dirty_region_list(dirty_region_list),
- _num_dirty_regions(num_dirty_regions),
+ _regions(regions),
_chunk_length(chunk_length),
- _cur_dirty_regions(0) {
+ _cur_dirty_regions(0),
+ _scan_state(scan_state) {
assert(chunk_length > 0, "must be");
}
- static size_t chunk_size() { return M; }
+ static uint chunk_size() { return M; }
void work(uint worker_id) {
- while (_cur_dirty_regions < _num_dirty_regions) {
- size_t next = Atomic::add(_chunk_length, &_cur_dirty_regions) - _chunk_length;
- size_t max = MIN2(next + _chunk_length, _num_dirty_regions);
+ while (_cur_dirty_regions < _regions->size()) {
+ uint next = Atomic::add(_chunk_length, &_cur_dirty_regions) - _chunk_length;
+ uint max = MIN2(next + _chunk_length, _regions->size());
- for (size_t i = next; i < max; i++) {
- HeapRegion* r = _g1h->region_at(_dirty_region_list[i]);
+ for (uint i = next; i < max; i++) {
+ HeapRegion* r = _g1h->region_at(_regions->at(i));
if (!r->is_survivor()) {
r->clear_cardtable();
}
@@ -94,159 +508,222 @@
}
};
- size_t _max_regions;
-
- // Scan progress for the remembered set of a single region. Transitions from
- // Unclaimed -> Claimed -> Complete.
- // At each of the transitions the thread that does the transition needs to perform
- // some special action once. This is the reason for the extra "Claimed" state.
- typedef jint G1RemsetIterState;
-
- static const G1RemsetIterState Unclaimed = 0; // The remembered set has not been scanned yet.
- static const G1RemsetIterState Claimed = 1; // The remembered set is currently being scanned.
- static const G1RemsetIterState Complete = 2; // The remembered set has been completely scanned.
+ // Clear the card table of "dirty" regions.
+ void clear_card_table(WorkGang* workers) {
+ uint num_regions = _all_dirty_regions->size();
- G1RemsetIterState volatile* _iter_states;
- // The current location where the next thread should continue scanning in a region's
- // remembered set.
- size_t volatile* _iter_claims;
+ if (num_regions == 0) {
+ return;
+ }
- // Temporary buffer holding the regions we used to store remembered set scan duplicate
- // information. These are also called "dirty". Valid entries are from [0.._cur_dirty_region)
- uint* _dirty_region_buffer;
-
- // Flag for every region whether it is in the _dirty_region_buffer already
- // to avoid duplicates.
- bool volatile* _in_dirty_region_buffer;
- size_t _cur_dirty_region;
+ uint const num_chunks = (uint)(align_up((size_t)num_regions << HeapRegion::LogCardsPerRegion, G1ClearCardTableTask::chunk_size()) / G1ClearCardTableTask::chunk_size());
+ uint const num_workers = MIN2(num_chunks, workers->active_workers());
+ uint const chunk_length = G1ClearCardTableTask::chunk_size() / (uint)HeapRegion::CardsPerRegion;
- // Creates a snapshot of the current _top values at the start of collection to
- // filter out card marks that we do not want to scan.
- class G1ResetScanTopClosure : public HeapRegionClosure {
- private:
- HeapWord** _scan_top;
- public:
- G1ResetScanTopClosure(HeapWord** scan_top) : _scan_top(scan_top) { }
+ // Iterate over the dirty cards region list.
+ G1ClearCardTableTask cl(G1CollectedHeap::heap(), _all_dirty_regions, chunk_length, this);
- virtual bool do_heap_region(HeapRegion* r) {
- uint hrm_index = r->hrm_index();
- if (!r->in_collection_set() && r->is_old_or_humongous_or_archive() && !r->is_empty()) {
- _scan_top[hrm_index] = r->top();
- } else {
- _scan_top[hrm_index] = NULL;
- }
- return false;
- }
- };
+ log_debug(gc, ergo)("Running %s using %u workers for %u "
+ "units of work for %u regions.",
+ cl.name(), num_workers, num_chunks, num_regions);
+ workers->run_task(&cl, num_workers);
- // For each region, contains the maximum top() value to be used during this garbage
- // collection. Subsumes common checks like filtering out everything but old and
- // humongous regions outside the collection set.
- // This is valid because we are not interested in scanning stray remembered set
- // entries from free or archive regions.
- HeapWord** _scan_top;
+#ifndef PRODUCT
+ G1CollectedHeap::heap()->verifier()->verify_card_table_cleanup();
+#endif
+ }
+
public:
G1RemSetScanState() :
_max_regions(0),
- _iter_states(NULL),
- _iter_claims(NULL),
- _dirty_region_buffer(NULL),
- _in_dirty_region_buffer(NULL),
- _cur_dirty_region(0),
+ _collection_set_iter_state(NULL),
+ _card_table_scan_state(NULL),
+ _scan_chunks_per_region((uint)(HeapRegion::CardsPerRegion / CardsPerChunk)),
+ _region_scan_chunks(NULL),
+ _scan_chunks_shift(0),
+ _all_dirty_regions(NULL),
+ _next_dirty_regions(NULL),
_scan_top(NULL) {
}
~G1RemSetScanState() {
- if (_iter_states != NULL) {
- FREE_C_HEAP_ARRAY(G1RemsetIterState, _iter_states);
- }
- if (_iter_claims != NULL) {
- FREE_C_HEAP_ARRAY(size_t, _iter_claims);
- }
- if (_dirty_region_buffer != NULL) {
- FREE_C_HEAP_ARRAY(uint, _dirty_region_buffer);
- }
- if (_in_dirty_region_buffer != NULL) {
- FREE_C_HEAP_ARRAY(bool, _in_dirty_region_buffer);
- }
- if (_scan_top != NULL) {
- FREE_C_HEAP_ARRAY(HeapWord*, _scan_top);
- }
+ FREE_C_HEAP_ARRAY(G1RemsetIterState, _collection_set_iter_state);
+ FREE_C_HEAP_ARRAY(uint, _card_table_scan_state);
+ FREE_C_HEAP_ARRAY(bool, _region_scan_chunks);
+ FREE_C_HEAP_ARRAY(HeapWord*, _scan_top);
}
- void initialize(uint max_regions) {
- assert(_iter_states == NULL, "Must not be initialized twice");
- assert(_iter_claims == NULL, "Must not be initialized twice");
+ void initialize(size_t max_regions) {
+ assert(_collection_set_iter_state == NULL, "Must not be initialized twice");
_max_regions = max_regions;
- _iter_states = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC);
- _iter_claims = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC);
- _dirty_region_buffer = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC);
- _in_dirty_region_buffer = NEW_C_HEAP_ARRAY(bool, max_regions, mtGC);
+ _collection_set_iter_state = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC);
+ _card_table_scan_state = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC);
+ _region_scan_chunks = NEW_C_HEAP_ARRAY(bool, max_regions * _scan_chunks_per_region, mtGC);
+
+ _scan_chunks_shift = (uint8_t)log2_intptr(HeapRegion::CardsPerRegion / _scan_chunks_per_region);
_scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC);
}
- void reset() {
- for (uint i = 0; i < _max_regions; i++) {
- _iter_states[i] = Unclaimed;
- clear_scan_top(i);
+ void prepare() {
+ for (size_t i = 0; i < _max_regions; i++) {
+ _collection_set_iter_state[i] = false;
+ clear_scan_top((uint)i);
}
- G1ResetScanTopClosure cl(_scan_top);
+ _all_dirty_regions = new G1DirtyRegions(_max_regions);
+
+ G1ResetScanTopClosure cl(this);
G1CollectedHeap::heap()->heap_region_iterate(&cl);
- memset((void*)_iter_claims, 0, _max_regions * sizeof(size_t));
- memset((void*)_in_dirty_region_buffer, false, _max_regions * sizeof(bool));
- _cur_dirty_region = 0;
+ _next_dirty_regions = new G1DirtyRegions(_max_regions);
}
- // Attempt to claim the remembered set of the region for iteration. Returns true
- // if this call caused the transition from Unclaimed to Claimed.
- inline bool claim_iter(uint region) {
- assert(region < _max_regions, "Tried to access invalid region %u", region);
- if (_iter_states[region] != Unclaimed) {
- return false;
+ void print_merge_heap_roots_stats() {
+ size_t num_scan_chunks = 0;
+ for (uint i = 0; i < _max_regions * _scan_chunks_per_region; i++) {
+ if (_region_scan_chunks[i]) {
+ num_scan_chunks++;
+ }
}
- G1RemsetIterState res = Atomic::cmpxchg(Claimed, &_iter_states[region], Unclaimed);
- return (res == Unclaimed);
+ size_t num_visited_cards = num_scan_chunks * CardsPerChunk;
+ size_t total_dirty_region_cards = _next_dirty_regions->size() * HeapRegion::CardsPerRegion;
+
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ size_t total_old_region_cards =
+ (g1h->num_regions() - (g1h->num_free_regions() - g1h->collection_set()->cur_length())) * HeapRegion::CardsPerRegion;
+
+ log_debug(gc,remset)("Visited cards " SIZE_FORMAT " Total dirty " SIZE_FORMAT " (%.2lf%%) Total old " SIZE_FORMAT " (%.2lf%%)",
+ num_visited_cards,
+ total_dirty_region_cards,
+ percent_of(num_visited_cards, total_dirty_region_cards),
+ total_old_region_cards,
+ percent_of(num_visited_cards, total_old_region_cards));
}
- // Try to atomically sets the iteration state to "complete". Returns true for the
- // thread that caused the transition.
- inline bool set_iter_complete(uint region) {
- if (iter_is_complete(region)) {
- return false;
+ void merge_heap_roots(WorkGang* workers, bool remembered_set_only, G1GCPhaseTimes::GCParPhases merge_phase) {
+ {
+ _all_dirty_regions->merge(_next_dirty_regions);
+ _next_dirty_regions->reset();
+ for (size_t i = 0; i < _max_regions; i++) {
+ _card_table_scan_state[i] = 0;
+ }
+
+ ::memset(_region_scan_chunks, false, _max_regions * _scan_chunks_per_region * sizeof(*_region_scan_chunks));
}
- G1RemsetIterState res = Atomic::cmpxchg(Complete, &_iter_states[region], Claimed);
- return (res == Claimed);
+
+ size_t const increment_length = G1CollectedHeap::heap()->collection_set()->increment_length();
+
+ uint const num_workers = !remembered_set_only ? workers->active_workers() :
+ MIN2(workers->active_workers(), (uint)increment_length);
+
+ {
+ G1MergeHeapRootsTask cl(this, num_workers, remembered_set_only, merge_phase);
+ log_debug(gc, ergo)("Running %s using %u workers for " SIZE_FORMAT " regions",
+ cl.name(), num_workers, increment_length);
+ workers->run_task(&cl, num_workers);
+ }
+
+ if (log_is_enabled(Debug, gc, remset)) {
+ print_merge_heap_roots_stats();
+ }
}
- // Returns true if the region's iteration is complete.
- inline bool iter_is_complete(uint region) const {
- assert(region < _max_regions, "Tried to access invalid region %u", region);
- return _iter_states[region] == Complete;
+ void set_chunk_region_dirty(size_t const region_card_idx) {
+ size_t chunk_idx = region_card_idx >> _scan_chunks_shift;
+ for (uint i = 0; i < _scan_chunks_per_region; i++) {
+ _region_scan_chunks[chunk_idx++] = true;
+ }
+ }
+
+ void set_chunk_dirty(size_t const card_idx) {
+ assert((card_idx >> _scan_chunks_shift) < (_max_regions * _scan_chunks_per_region),
+ "Trying to access index " SIZE_FORMAT " out of bounds " SIZE_FORMAT,
+ card_idx >> _scan_chunks_shift, _max_regions * _scan_chunks_per_region);
+ size_t const chunk_idx = card_idx >> _scan_chunks_shift;
+ if (!_region_scan_chunks[chunk_idx]) {
+ _region_scan_chunks[chunk_idx] = true;
+ }
}
- // The current position within the remembered set of the given region.
- inline size_t iter_claimed(uint region) const {
- assert(region < _max_regions, "Tried to access invalid region %u", region);
- return _iter_claims[region];
+ void cleanup(WorkGang* workers) {
+ _all_dirty_regions->merge(_next_dirty_regions);
+
+ clear_card_table(workers);
+
+ delete _all_dirty_regions;
+ _all_dirty_regions = NULL;
+
+ delete _next_dirty_regions;
+ _next_dirty_regions = NULL;
}
- // Claim the next block of cards within the remembered set of the region with
- // step size.
- inline size_t iter_claimed_next(uint region, size_t step) {
- return Atomic::add(step, &_iter_claims[region]) - step;
- }
+ void iterate_dirty_regions_from(HeapRegionClosure* cl, uint worker_id) {
+ uint num_regions = _next_dirty_regions->size();
- void add_dirty_region(uint region) {
- if (_in_dirty_region_buffer[region]) {
+ if (num_regions == 0) {
return;
}
- if (!Atomic::cmpxchg(true, &_in_dirty_region_buffer[region], false)) {
- size_t allocated = Atomic::add(1u, &_cur_dirty_region) - 1;
- _dirty_region_buffer[allocated] = region;
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+ WorkGang* workers = g1h->workers();
+ uint const max_workers = workers->active_workers();
+
+ uint const start_pos = num_regions * worker_id / max_workers;
+ uint cur = start_pos;
+
+ do {
+ bool result = cl->do_heap_region(g1h->region_at(_next_dirty_regions->at(cur)));
+ guarantee(!result, "Not allowed to ask for early termination.");
+ cur++;
+ if (cur == _next_dirty_regions->size()) {
+ cur = 0;
+ }
+ } while (cur != start_pos);
+ }
+
+ // Attempt to claim the given region in the collection set for iteration. Returns true
+ // if this call caused the transition from Unclaimed to Claimed.
+ inline bool claim_collection_set_region(uint region) {
+ assert(region < _max_regions, "Tried to access invalid region %u", region);
+ if (_collection_set_iter_state[region]) {
+ return false;
}
+ return !Atomic::cmpxchg(true, &_collection_set_iter_state[region], false);
+ }
+
+ bool has_cards_to_scan(uint region) {
+ assert(region < _max_regions, "Tried to access invalid region %u", region);
+ return _card_table_scan_state[region] < HeapRegion::CardsPerRegion;
+ }
+
+ uint claim_cards_to_scan(uint region, uint increment) {
+ assert(region < _max_regions, "Tried to access invalid region %u", region);
+ return Atomic::add(increment, &_card_table_scan_state[region]) - increment;
+ }
+
+ void add_dirty_region(uint const region) {
+#ifdef ASSERT
+ HeapRegion* hr = G1CollectedHeap::heap()->region_at(region);
+ assert(!hr->in_collection_set() && hr->is_old_or_humongous_or_archive(),
+ "Region %u is not suitable for scanning, is %sin collection set or %s",
+ hr->hrm_index(), hr->in_collection_set() ? "" : "not ", hr->get_short_type_str());
+#endif
+ _next_dirty_regions->add_dirty_region(region);
+ }
+
+ void add_all_dirty_region(uint region) {
+#ifdef ASSERT
+ HeapRegion* hr = G1CollectedHeap::heap()->region_at(region);
+ assert(hr->in_collection_set(),
+ "Only add young regions to all dirty regions directly but %u is %s",
+ hr->hrm_index(), hr->get_short_type_str());
+#endif
+ _all_dirty_regions->add_dirty_region(region);
+ }
+
+ void set_scan_top(uint region_idx, HeapWord* value) {
+ _scan_top[region_idx] = value;
}
HeapWord* scan_top(uint region_idx) const {
@@ -254,30 +731,7 @@
}
void clear_scan_top(uint region_idx) {
- _scan_top[region_idx] = NULL;
- }
-
- // Clear the card table of "dirty" regions.
- void clear_card_table(WorkGang* workers) {
- if (_cur_dirty_region == 0) {
- return;
- }
-
- size_t const num_chunks = align_up(_cur_dirty_region * HeapRegion::CardsPerRegion, G1ClearCardTableTask::chunk_size()) / G1ClearCardTableTask::chunk_size();
- uint const num_workers = (uint)MIN2(num_chunks, (size_t)workers->active_workers());
- size_t const chunk_length = G1ClearCardTableTask::chunk_size() / HeapRegion::CardsPerRegion;
-
- // Iterate over the dirty cards region list.
- G1ClearCardTableTask cl(G1CollectedHeap::heap(), _dirty_region_buffer, _cur_dirty_region, chunk_length);
-
- log_debug(gc, ergo)("Running %s using %u workers for " SIZE_FORMAT " "
- "units of work for " SIZE_FORMAT " regions.",
- cl.name(), num_workers, num_chunks, _cur_dirty_region);
- workers->run_task(&cl, num_workers);
-
-#ifndef PRODUCT
- G1CollectedHeap::heap()->verifier()->verify_card_table_cleanup();
-#endif
+ set_scan_top(region_idx, NULL);
}
};
@@ -294,9 +748,7 @@
}
G1RemSet::~G1RemSet() {
- if (_scan_state != NULL) {
- delete _scan_state;
- }
+ delete _scan_state;
}
uint G1RemSet::num_par_rem_sets() {
@@ -308,181 +760,252 @@
_scan_state->initialize(max_regions);
}
-class G1ScanRSForRegionClosure : public HeapRegionClosure {
+// Helper class to scan and detect ranges of cards that need to be scanned on the
+// card table.
+class G1CardTableScanner : public StackObj {
+public:
+ typedef CardTable::CardValue CardValue;
+
+private:
+ CardValue* const _base_addr;
+
+ CardValue* _cur_addr;
+ CardValue* const _end_addr;
+
+ static const size_t ToScanMask = G1CardTable::g1_card_already_scanned;
+ static const size_t ExpandedToScanMask = G1CardTable::WordAlreadyScanned;
+
+ bool cur_addr_aligned() const {
+ return ((uintptr_t)_cur_addr) % sizeof(size_t) == 0;
+ }
+
+ bool cur_card_is_dirty() const {
+ CardValue value = *_cur_addr;
+ return (value & ToScanMask) == 0;
+ }
+
+ bool cur_word_of_cards_contains_any_dirty_card() const {
+ assert(cur_addr_aligned(), "Current address should be aligned");
+ size_t const value = *(size_t*)_cur_addr;
+ return (~value & ExpandedToScanMask) != 0;
+ }
+
+ bool cur_word_of_cards_all_dirty_cards() const {
+ size_t const value = *(size_t*)_cur_addr;
+ return value == G1CardTable::WordAllDirty;
+ }
+
+ size_t get_and_advance_pos() {
+ _cur_addr++;
+ return pointer_delta(_cur_addr, _base_addr, sizeof(CardValue)) - 1;
+ }
+
+public:
+ G1CardTableScanner(CardValue* start_card, size_t size) :
+ _base_addr(start_card),
+ _cur_addr(start_card),
+ _end_addr(start_card + size) {
+
+ assert(is_aligned(start_card, sizeof(size_t)), "Unaligned start addr " PTR_FORMAT, p2i(start_card));
+ assert(is_aligned(size, sizeof(size_t)), "Unaligned size " SIZE_FORMAT, size);
+ }
+
+ size_t find_next_dirty() {
+ while (!cur_addr_aligned()) {
+ if (cur_card_is_dirty()) {
+ return get_and_advance_pos();
+ }
+ _cur_addr++;
+ }
+
+ assert(cur_addr_aligned(), "Current address should be aligned now.");
+ while (_cur_addr != _end_addr) {
+ if (cur_word_of_cards_contains_any_dirty_card()) {
+ for (size_t i = 0; i < sizeof(size_t); i++) {
+ if (cur_card_is_dirty()) {
+ return get_and_advance_pos();
+ }
+ _cur_addr++;
+ }
+ assert(false, "Should not reach here given we detected a dirty card in the word.");
+ }
+ _cur_addr += sizeof(size_t);
+ }
+ return get_and_advance_pos();
+ }
+
+ size_t find_next_non_dirty() {
+ assert(_cur_addr <= _end_addr, "Not allowed to search for marks after area.");
+
+ while (!cur_addr_aligned()) {
+ if (!cur_card_is_dirty()) {
+ return get_and_advance_pos();
+ }
+ _cur_addr++;
+ }
+
+ assert(cur_addr_aligned(), "Current address should be aligned now.");
+ while (_cur_addr != _end_addr) {
+ if (!cur_word_of_cards_all_dirty_cards()) {
+ for (size_t i = 0; i < sizeof(size_t); i++) {
+ if (!cur_card_is_dirty()) {
+ return get_and_advance_pos();
+ }
+ _cur_addr++;
+ }
+ assert(false, "Should not reach here given we detected a non-dirty card in the word.");
+ }
+ _cur_addr += sizeof(size_t);
+ }
+ return get_and_advance_pos();
+ }
+};
+
+// Helper class to claim dirty chunks within the card table.
+class G1CardTableChunkClaimer {
+ G1RemSetScanState* _scan_state;
+ uint _region_idx;
+ uint _cur_claim;
+
+public:
+ G1CardTableChunkClaimer(G1RemSetScanState* scan_state, uint region_idx) :
+ _scan_state(scan_state),
+ _region_idx(region_idx),
+ _cur_claim(0) {
+ guarantee(size() <= HeapRegion::CardsPerRegion, "Should not claim more space than possible.");
+ }
+
+ bool has_next() {
+ while (true) {
+ _cur_claim = _scan_state->claim_cards_to_scan(_region_idx, size());
+ if (_cur_claim >= HeapRegion::CardsPerRegion) {
+ return false;
+ }
+ if (_scan_state->chunk_needs_scan(_region_idx, _cur_claim)) {
+ return true;
+ }
+ }
+ }
+
+ uint value() const { return _cur_claim; }
+ uint size() const { return _scan_state->scan_chunk_size(); }
+};
+
+// Scans a heap region for dirty cards.
+class G1ScanHRForRegionClosure : public HeapRegionClosure {
G1CollectedHeap* _g1h;
- G1CardTable *_ct;
+ G1CardTable* _ct;
+ G1BlockOffsetTable* _bot;
G1ParScanThreadState* _pss;
- G1ScanCardClosure* _scan_objs_on_card_cl;
G1RemSetScanState* _scan_state;
G1GCPhaseTimes::GCParPhases _phase;
- uint _worker_i;
-
- size_t _opt_refs_scanned;
- size_t _opt_refs_memory_used;
+ uint _worker_id;
size_t _cards_scanned;
- size_t _cards_claimed;
- size_t _cards_skipped;
+ size_t _blocks_scanned;
+ size_t _chunks_claimed;
Tickspan _rem_set_root_scan_time;
Tickspan _rem_set_trim_partially_time;
- Tickspan _strong_code_root_scan_time;
- Tickspan _strong_code_trim_partially_time;
-
- void claim_card(size_t card_index, const uint region_idx_for_card) {
- _ct->set_card_claimed(card_index);
- _scan_state->add_dirty_region(region_idx_for_card);
- }
-
- void scan_card(MemRegion mr, uint region_idx_for_card) {
+ void scan_memregion(uint region_idx_for_card, MemRegion mr) {
HeapRegion* const card_region = _g1h->region_at(region_idx_for_card);
- assert(!card_region->is_young(), "Should not scan card in young region %u", region_idx_for_card);
- card_region->oops_on_card_seq_iterate_careful<true>(mr, _scan_objs_on_card_cl);
- _scan_objs_on_card_cl->trim_queue_partially();
- _cards_scanned++;
+ G1ScanCardClosure card_cl(_g1h, _pss);
+ card_region->oops_on_card_seq_iterate_careful<true>(mr, &card_cl);
+ _pss->trim_queue_partially();
}
- void scan_opt_rem_set_roots(HeapRegion* r) {
- EventGCPhaseParallel event;
-
- G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r);
-
- G1ScanCardClosure scan_cl(_g1h, _pss);
- G1ScanRSForOptionalClosure cl(_g1h, &scan_cl);
- _opt_refs_scanned += opt_rem_set_list->oops_do(&cl, _pss->closures()->raw_strong_oops());
- _opt_refs_memory_used += opt_rem_set_list->used_memory();
-
- event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(_phase));
- }
-
- void scan_rem_set_roots(HeapRegion* r) {
- EventGCPhaseParallel event;
- uint const region_idx = r->hrm_index();
-
- if (_scan_state->claim_iter(region_idx)) {
- // If we ever free the collection set concurrently, we should also
- // clear the card table concurrently therefore we won't need to
- // add regions of the collection set to the dirty cards region.
- _scan_state->add_dirty_region(region_idx);
- }
-
- if (r->rem_set()->cardset_is_empty()) {
+ void do_claimed_block(uint const region_idx_for_card, size_t const first_card, size_t const num_cards) {
+ HeapWord* const card_start = _bot->address_for_index_raw(first_card);
+#ifdef ASSERT
+ HeapRegion* hr = _g1h->region_at_or_null(region_idx_for_card);
+ assert(hr == NULL || hr->is_in_reserved(card_start),
+ "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
+#endif
+ HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
+ if (card_start >= top) {
return;
}
- // We claim cards in blocks so as to reduce the contention.
- size_t const block_size = G1RSetScanBlockSize;
-
- HeapRegionRemSetIterator iter(r->rem_set());
- size_t card_index;
-
- size_t claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
- for (size_t current_card = 0; iter.has_next(card_index); current_card++) {
- if (current_card >= claimed_card_block + block_size) {
- claimed_card_block = _scan_state->iter_claimed_next(region_idx, block_size);
- }
- if (current_card < claimed_card_block) {
- _cards_skipped++;
- continue;
- }
- _cards_claimed++;
-
- HeapWord* const card_start = _g1h->bot()->address_for_index_raw(card_index);
- uint const region_idx_for_card = _g1h->addr_to_region(card_start);
+ MemRegion mr(card_start, MIN2(card_start + ((size_t)num_cards << BOTConstants::LogN_words), top));
+ scan_memregion(region_idx_for_card, mr);
-#ifdef ASSERT
- HeapRegion* hr = _g1h->region_at_or_null(region_idx_for_card);
- assert(hr == NULL || hr->is_in_reserved(card_start),
- "Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
-#endif
- HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
- if (card_start >= top) {
- continue;
- }
+ _cards_scanned += num_cards;
+ }
- // If the card is dirty, then G1 will scan it during Update RS.
- if (_ct->is_card_claimed(card_index) || _ct->is_card_dirty(card_index)) {
- continue;
- }
-
- // We claim lazily (so races are possible but they're benign), which reduces the
- // number of duplicate scans (the rsets of the regions in the cset can intersect).
- // Claim the card after checking bounds above: the remembered set may contain
- // random cards into current survivor, and we would then have an incorrectly
- // claimed card in survivor space. Card table clear does not reset the card table
- // of survivor space regions.
- claim_card(card_index, region_idx_for_card);
-
- MemRegion const mr(card_start, MIN2(card_start + BOTConstants::N_words, top));
-
- scan_card(mr, region_idx_for_card);
- }
- event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(_phase));
+ ALWAYSINLINE void do_card_block(uint const region_idx, size_t const first_card, size_t const num_cards) {
+ _ct->mark_as_scanned(first_card, num_cards);
+ do_claimed_block(region_idx, first_card, num_cards);
+ _blocks_scanned++;
}
- void scan_strong_code_roots(HeapRegion* r) {
+ void scan_heap_roots(HeapRegion* r) {
EventGCPhaseParallel event;
- // We pass a weak code blobs closure to the remembered set scanning because we want to avoid
- // treating the nmethods visited to act as roots for concurrent marking.
- // We only want to make sure that the oops in the nmethods are adjusted with regard to the
- // objects copied by the current evacuation.
- r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
- event.commit(GCId::current(), _worker_i, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::CodeRoots));
+ uint const region_idx = r->hrm_index();
+
+ ResourceMark rm;
+
+ G1CardTableChunkClaimer claim(_scan_state, region_idx);
+
+ while (claim.has_next()) {
+ size_t const region_card_base_idx = ((size_t)region_idx << HeapRegion::LogCardsPerRegion) + claim.value();
+ CardTable::CardValue* const base_addr = _ct->byte_for_index(region_card_base_idx);
+
+ G1CardTableScanner scan(base_addr, claim.size());
+
+ size_t first_scan_idx = scan.find_next_dirty();
+ while (first_scan_idx != claim.size()) {
+ assert(*_ct->byte_for_index(region_card_base_idx + first_scan_idx) <= 0x1, "is %d at region %u idx " SIZE_FORMAT, *_ct->byte_for_index(region_card_base_idx + first_scan_idx), region_idx, first_scan_idx);
+
+ size_t const last_scan_idx = scan.find_next_non_dirty();
+ size_t const len = last_scan_idx - first_scan_idx;
+
+ do_card_block(region_idx, region_card_base_idx + first_scan_idx, len);
+
+ if (last_scan_idx == claim.size()) {
+ break;
+ }
+
+ first_scan_idx = scan.find_next_dirty();
+ }
+ _chunks_claimed++;
+ }
+
+ event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(G1GCPhaseTimes::ScanHR));
}
public:
- G1ScanRSForRegionClosure(G1RemSetScanState* scan_state,
- G1ScanCardClosure* scan_obj_on_card,
+ G1ScanHRForRegionClosure(G1RemSetScanState* scan_state,
G1ParScanThreadState* pss,
- G1GCPhaseTimes::GCParPhases phase,
- uint worker_i) :
+ uint worker_id,
+ G1GCPhaseTimes::GCParPhases phase) :
_g1h(G1CollectedHeap::heap()),
_ct(_g1h->card_table()),
+ _bot(_g1h->bot()),
_pss(pss),
- _scan_objs_on_card_cl(scan_obj_on_card),
_scan_state(scan_state),
_phase(phase),
- _worker_i(worker_i),
- _opt_refs_scanned(0),
- _opt_refs_memory_used(0),
+ _worker_id(worker_id),
_cards_scanned(0),
- _cards_claimed(0),
- _cards_skipped(0),
+ _blocks_scanned(0),
+ _chunks_claimed(0),
_rem_set_root_scan_time(),
- _rem_set_trim_partially_time(),
- _strong_code_root_scan_time(),
- _strong_code_trim_partially_time() { }
+ _rem_set_trim_partially_time() {
+ }
bool do_heap_region(HeapRegion* r) {
- assert(r->in_collection_set(), "Region %u is not in the collection set.", r->hrm_index());
+ assert(!r->in_collection_set() && r->is_old_or_humongous_or_archive(),
+ "Should only be called on old gen non-collection set regions but region %u is not.",
+ r->hrm_index());
uint const region_idx = r->hrm_index();
- // The individual references for the optional remembered set are per-worker, so we
- // always need to scan them.
- if (r->has_index_in_opt_cset()) {
+ if (_scan_state->has_cards_to_scan(region_idx)) {
G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
- scan_opt_rem_set_roots(r);
- }
-
- // Do an early out if we know we are complete.
- if (_scan_state->iter_is_complete(region_idx)) {
- return false;
- }
-
- {
- G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_root_scan_time, _rem_set_trim_partially_time);
- scan_rem_set_roots(r);
- }
-
- if (_scan_state->set_iter_complete(region_idx)) {
- G1EvacPhaseWithTrimTimeTracker timer(_pss, _strong_code_root_scan_time, _strong_code_trim_partially_time);
- // Scan the strong code root list attached to the current region
- scan_strong_code_roots(r);
+ scan_heap_roots(r);
}
return false;
}
@@ -490,120 +1013,156 @@
Tickspan rem_set_root_scan_time() const { return _rem_set_root_scan_time; }
Tickspan rem_set_trim_partially_time() const { return _rem_set_trim_partially_time; }
+ size_t cards_scanned() const { return _cards_scanned; }
+ size_t blocks_scanned() const { return _blocks_scanned; }
+ size_t chunks_claimed() const { return _chunks_claimed; }
+};
+
+void G1RemSet::scan_heap_roots(G1ParScanThreadState* pss,
+ uint worker_id,
+ G1GCPhaseTimes::GCParPhases scan_phase,
+ G1GCPhaseTimes::GCParPhases objcopy_phase) {
+ G1ScanHRForRegionClosure cl(_scan_state, pss, worker_id, scan_phase);
+ _scan_state->iterate_dirty_regions_from(&cl, worker_id);
+
+ G1GCPhaseTimes* p = _g1p->phase_times();
+
+ p->record_or_add_time_secs(objcopy_phase, worker_id, cl.rem_set_trim_partially_time().seconds());
+
+ p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_root_scan_time().seconds());
+ p->record_or_add_thread_work_item(scan_phase, worker_id, cl.cards_scanned(), G1GCPhaseTimes::ScanHRScannedCards);
+ p->record_or_add_thread_work_item(scan_phase, worker_id, cl.blocks_scanned(), G1GCPhaseTimes::ScanHRScannedBlocks);
+ p->record_or_add_thread_work_item(scan_phase, worker_id, cl.chunks_claimed(), G1GCPhaseTimes::ScanHRClaimedChunks);
+}
+
+// Heap region closure to be applied to all regions in the current collection set
+// increment to fix up non-card related roots.
+class G1ScanCollectionSetRegionClosure : public HeapRegionClosure {
+ G1ParScanThreadState* _pss;
+ G1RemSetScanState* _scan_state;
+
+ G1GCPhaseTimes::GCParPhases _scan_phase;
+ G1GCPhaseTimes::GCParPhases _code_roots_phase;
+
+ uint _worker_id;
+
+ size_t _opt_refs_scanned;
+ size_t _opt_refs_memory_used;
+
+ Tickspan _strong_code_root_scan_time;
+ Tickspan _strong_code_trim_partially_time;
+
+ Tickspan _rem_set_opt_root_scan_time;
+ Tickspan _rem_set_opt_trim_partially_time;
+
+ void scan_opt_rem_set_roots(HeapRegion* r) {
+ EventGCPhaseParallel event;
+
+ G1OopStarChunkedList* opt_rem_set_list = _pss->oops_into_optional_region(r);
+
+ G1ScanCardClosure scan_cl(G1CollectedHeap::heap(), _pss);
+ G1ScanRSForOptionalClosure cl(G1CollectedHeap::heap(), &scan_cl);
+ _opt_refs_scanned += opt_rem_set_list->oops_do(&cl, _pss->closures()->raw_strong_oops());
+ _opt_refs_memory_used += opt_rem_set_list->used_memory();
+
+ event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_scan_phase));
+ }
+
+public:
+ G1ScanCollectionSetRegionClosure(G1RemSetScanState* scan_state,
+ G1ParScanThreadState* pss,
+ uint worker_i,
+ G1GCPhaseTimes::GCParPhases scan_phase,
+ G1GCPhaseTimes::GCParPhases code_roots_phase) :
+ _pss(pss),
+ _scan_state(scan_state),
+ _scan_phase(scan_phase),
+ _code_roots_phase(code_roots_phase),
+ _worker_id(worker_i),
+ _opt_refs_scanned(0),
+ _opt_refs_memory_used(0),
+ _strong_code_root_scan_time(),
+ _strong_code_trim_partially_time(),
+ _rem_set_opt_root_scan_time(),
+ _rem_set_opt_trim_partially_time() { }
+
+ bool do_heap_region(HeapRegion* r) {
+ uint const region_idx = r->hrm_index();
+
+ // The individual references for the optional remembered set are per-worker, so we
+ // always need to scan them.
+ if (r->has_index_in_opt_cset()) {
+ G1EvacPhaseWithTrimTimeTracker timer(_pss, _rem_set_opt_root_scan_time, _rem_set_opt_trim_partially_time);
+ scan_opt_rem_set_roots(r);
+ }
+
+ if (_scan_state->claim_collection_set_region(region_idx)) {
+ EventGCPhaseParallel event;
+
+ G1EvacPhaseWithTrimTimeTracker timer(_pss, _strong_code_root_scan_time, _strong_code_trim_partially_time);
+ // Scan the strong code root list attached to the current region
+ r->strong_code_roots_do(_pss->closures()->weak_codeblobs());
+
+ event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_code_roots_phase));
+ }
+
+ return false;
+ }
+
Tickspan strong_code_root_scan_time() const { return _strong_code_root_scan_time; }
Tickspan strong_code_root_trim_partially_time() const { return _strong_code_trim_partially_time; }
- size_t cards_scanned() const { return _cards_scanned; }
- size_t cards_claimed() const { return _cards_claimed; }
- size_t cards_skipped() const { return _cards_skipped; }
+ Tickspan rem_set_opt_root_scan_time() const { return _rem_set_opt_root_scan_time; }
+ Tickspan rem_set_opt_trim_partially_time() const { return _rem_set_opt_trim_partially_time; }
size_t opt_refs_scanned() const { return _opt_refs_scanned; }
size_t opt_refs_memory_used() const { return _opt_refs_memory_used; }
};
-void G1RemSet::scan_rem_set(G1ParScanThreadState* pss,
- uint worker_i,
- G1GCPhaseTimes::GCParPhases scan_phase,
- G1GCPhaseTimes::GCParPhases objcopy_phase,
- G1GCPhaseTimes::GCParPhases coderoots_phase) {
- assert(pss->trim_ticks().value() == 0, "Queues must have been trimmed before entering.");
-
- G1ScanCardClosure scan_cl(_g1h, pss);
- G1ScanRSForRegionClosure cl(_scan_state, &scan_cl, pss, scan_phase, worker_i);
- _g1h->collection_set_iterate_increment_from(&cl, worker_i);
-
- G1GCPhaseTimes* p = _g1p->phase_times();
-
- p->record_or_add_time_secs(objcopy_phase, worker_i, cl.rem_set_trim_partially_time().seconds());
+void G1RemSet::scan_collection_set_regions(G1ParScanThreadState* pss,
+ uint worker_id,
+ G1GCPhaseTimes::GCParPhases scan_phase,
+ G1GCPhaseTimes::GCParPhases coderoots_phase,
+ G1GCPhaseTimes::GCParPhases objcopy_phase) {
+ G1ScanCollectionSetRegionClosure cl(_scan_state, pss, worker_id, scan_phase, coderoots_phase);
+ _g1h->collection_set_iterate_increment_from(&cl, worker_id);
- p->record_or_add_time_secs(scan_phase, worker_i, cl.rem_set_root_scan_time().seconds());
- p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
- p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
- p->record_or_add_thread_work_item(scan_phase, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
- // At this time we only record some metrics for the optional remembered set.
- if (scan_phase == G1GCPhaseTimes::OptScanRS) {
- p->record_or_add_thread_work_item(scan_phase, worker_i, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanRSScannedOptRefs);
- p->record_or_add_thread_work_item(scan_phase, worker_i, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanRSUsedMemory);
- }
-
- p->record_or_add_time_secs(coderoots_phase, worker_i, cl.strong_code_root_scan_time().seconds());
- p->add_time_secs(objcopy_phase, worker_i, cl.strong_code_root_trim_partially_time().seconds());
-}
-
-// Closure used for updating rem sets. Only called during an evacuation pause.
-class G1RefineCardClosure: public G1CardTableEntryClosure {
- G1RemSet* _g1rs;
- G1ScanCardClosure* _update_rs_cl;
-
- size_t _cards_scanned;
- size_t _cards_skipped;
-public:
- G1RefineCardClosure(G1CollectedHeap* g1h, G1ScanCardClosure* update_rs_cl) :
- _g1rs(g1h->rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
- {}
+ G1GCPhaseTimes* p = _g1h->phase_times();
- bool do_card_ptr(CardValue* card_ptr, uint worker_i) {
- // The only time we care about recording cards that
- // contain references that point into the collection set
- // is during RSet updating within an evacuation pause.
- // In this case worker_i should be the id of a GC worker thread.
- assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
-
- bool card_scanned = _g1rs->refine_card_during_gc(card_ptr, _update_rs_cl);
-
- if (card_scanned) {
- _update_rs_cl->trim_queue_partially();
- _cards_scanned++;
- } else {
- _cards_skipped++;
- }
- return true;
- }
-
- size_t cards_scanned() const { return _cards_scanned; }
- size_t cards_skipped() const { return _cards_skipped; }
-};
+ p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_root_scan_time().seconds());
+ p->record_or_add_time_secs(scan_phase, worker_id, cl.rem_set_opt_trim_partially_time().seconds());
-void G1RemSet::update_rem_set(G1ParScanThreadState* pss, uint worker_i) {
- G1GCPhaseTimes* p = _g1p->phase_times();
-
- // Apply closure to log entries in the HCC.
- if (G1HotCardCache::default_use_cache()) {
- G1EvacPhaseTimesTracker x(p, pss, G1GCPhaseTimes::ScanHCC, worker_i);
+ p->record_or_add_time_secs(coderoots_phase, worker_id, cl.strong_code_root_scan_time().seconds());
+ p->add_time_secs(objcopy_phase, worker_id, cl.strong_code_root_trim_partially_time().seconds());
- G1ScanCardClosure scan_hcc_cl(_g1h, pss);
- G1RefineCardClosure refine_card_cl(_g1h, &scan_hcc_cl);
- _g1h->iterate_hcc_closure(&refine_card_cl, worker_i);
- }
-
- // Now apply the closure to all remaining log entries.
- {
- G1EvacPhaseTimesTracker x(p, pss, G1GCPhaseTimes::UpdateRS, worker_i);
-
- G1ScanCardClosure update_rs_cl(_g1h, pss);
- G1RefineCardClosure refine_card_cl(_g1h, &update_rs_cl);
- _g1h->iterate_dirty_card_closure(&refine_card_cl, worker_i);
-
- p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_scanned(), G1GCPhaseTimes::UpdateRSScannedCards);
- p->record_thread_work_item(G1GCPhaseTimes::UpdateRS, worker_i, refine_card_cl.cards_skipped(), G1GCPhaseTimes::UpdateRSSkippedCards);
+ // At this time we record some metrics only for the evacuations after the initial one.
+ if (scan_phase == G1GCPhaseTimes::OptScanHR) {
+ p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_scanned(), G1GCPhaseTimes::ScanHRScannedOptRefs);
+ p->record_or_add_thread_work_item(scan_phase, worker_id, cl.opt_refs_memory_used(), G1GCPhaseTimes::ScanHRUsedMemory);
}
}
-void G1RemSet::prepare_for_scan_rem_set() {
- G1BarrierSet::dirty_card_queue_set().concatenate_logs();
- _scan_state->reset();
+void G1RemSet::prepare_for_scan_heap_roots() {
+ G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
+ dcqs.concatenate_logs();
+
+ _scan_state->prepare();
}
-void G1RemSet::prepare_for_scan_rem_set(uint region_idx) {
+void G1RemSet::merge_heap_roots(bool remembered_set_only, G1GCPhaseTimes::GCParPhases merge_phase) {
+ _scan_state->merge_heap_roots(_g1h->workers(), remembered_set_only, merge_phase);
+}
+
+void G1RemSet::prepare_for_scan_heap_roots(uint region_idx) {
_scan_state->clear_scan_top(region_idx);
}
-void G1RemSet::cleanup_after_scan_rem_set() {
+void G1RemSet::cleanup_after_scan_heap_roots() {
G1GCPhaseTimes* phase_times = _g1h->phase_times();
// Set all cards back to clean.
double start = os::elapsedTime();
- _scan_state->clear_card_table(_g1h->workers());
+ _scan_state->cleanup(_g1h->workers());
phase_times->record_clear_ct_time((os::elapsedTime() - start) * 1000.0);
}
@@ -759,53 +1318,6 @@
G1BarrierSet::shared_dirty_card_queue().enqueue(card_ptr);
}
-bool G1RemSet::refine_card_during_gc(CardValue* card_ptr,
- G1ScanCardClosure* update_rs_cl) {
- assert(_g1h->is_gc_active(), "Only call during GC");
-
- // Construct the region representing the card.
- HeapWord* card_start = _ct->addr_for(card_ptr);
- // And find the region containing it.
- uint const card_region_idx = _g1h->addr_to_region(card_start);
-
- HeapWord* scan_limit = _scan_state->scan_top(card_region_idx);
- if (scan_limit == NULL) {
- // This is a card into an uncommitted region. We need to bail out early as we
- // should not access the corresponding card table entry.
- return false;
- }
-
- check_card_ptr(card_ptr, _ct);
-
- // If the card is no longer dirty, nothing to do. This covers cards that were already
- // scanned as parts of the remembered sets.
- if (*card_ptr != G1CardTable::dirty_card_val()) {
- return false;
- }
-
- // We claim lazily (so races are possible but they're benign), which reduces the
- // number of potential duplicate scans (multiple threads may enqueue the same card twice).
- *card_ptr = G1CardTable::clean_card_val() | G1CardTable::claimed_card_val();
-
- _scan_state->add_dirty_region(card_region_idx);
- if (scan_limit <= card_start) {
- // If the card starts above the area in the region containing objects to scan, skip it.
- return false;
- }
-
- // Don't use addr_for(card_ptr + 1) which can ask for
- // a card beyond the heap.
- HeapWord* card_end = card_start + G1CardTable::card_size_in_words;
- MemRegion dirty_region(card_start, MIN2(scan_limit, card_end));
- assert(!dirty_region.is_empty(), "sanity");
-
- HeapRegion* const card_region = _g1h->region_at(card_region_idx);
- assert(!card_region->is_young(), "Should not scan card in young region %u", card_region_idx);
- bool card_processed = card_region->oops_on_card_seq_iterate_careful<true>(dirty_region, update_rs_cl);
- assert(card_processed, "must be");
- return true;
-}
-
void G1RemSet::print_periodic_summary_info(const char* header, uint period_count) {
if ((G1SummarizeRSetStatsPeriod > 0) && log_is_enabled(Trace, gc, remset) &&
(period_count % G1SummarizeRSetStatsPeriod == 0)) {
--- a/src/hotspot/share/gc/g1/g1RemSet.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1RemSet.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -46,6 +46,7 @@
class G1HotCardCache;
class G1RemSetScanState;
class G1ParScanThreadState;
+class G1ParScanThreadStateSet;
class G1Policy;
class G1ScanCardClosure;
class HeapRegionClaimer;
@@ -84,39 +85,39 @@
G1HotCardCache* hot_card_cache);
~G1RemSet();
- // Scan all remembered sets of the collection set for references into the collection
- // set.
- // Further applies heap_region_codeblobs on the oops of the unmarked nmethods on the strong code
- // roots list for each region in the collection set.
- void scan_rem_set(G1ParScanThreadState* pss,
- uint worker_i,
- G1GCPhaseTimes::GCParPhases scan_phase,
- G1GCPhaseTimes::GCParPhases objcopy_phase,
- G1GCPhaseTimes::GCParPhases coderoots_phase);
+ // Scan all cards in the non-collection set regions that potentially contain
+ // references into the current whole collection set.
+ void scan_heap_roots(G1ParScanThreadState* pss,
+ uint worker_id,
+ G1GCPhaseTimes::GCParPhases scan_phase,
+ G1GCPhaseTimes::GCParPhases objcopy_phase);
+
+ // Merge cards from various sources (remembered sets, hot card cache, log buffers)
+ // and calculate the cards that need to be scanned later (via scan_heap_roots()).
+ // If remembered_set_only is set, only merge remembered set cards.
+ void merge_heap_roots(bool remembered_set_only, G1GCPhaseTimes::GCParPhases merge_phase);
- // Flush remaining refinement buffers for cross-region references to either evacuate references
- // into the collection set or update the remembered set.
- void update_rem_set(G1ParScanThreadState* pss, uint worker_i);
-
- // Prepare for and cleanup after scanning the remembered sets. Must be called
+ // Prepare for and cleanup after scanning the heap roots. Must be called
// once before and after in sequential code.
- void prepare_for_scan_rem_set();
- void cleanup_after_scan_rem_set();
- // Prepares the given region for remembered set scanning.
- void prepare_for_scan_rem_set(uint region_idx);
+ void prepare_for_scan_heap_roots();
+ // Cleans the card table from temporary duplicate detection information.
+ void cleanup_after_scan_heap_roots();
+ // Prepares the given region for heap root scanning.
+ void prepare_for_scan_heap_roots(uint region_idx);
- G1RemSetScanState* scan_state() const { return _scan_state; }
+ // Do work for regions in the current increment of the collection set, scanning
+ // non-card based (heap) roots.
+ void scan_collection_set_regions(G1ParScanThreadState* pss,
+ uint worker_id,
+ G1GCPhaseTimes::GCParPhases scan_phase,
+ G1GCPhaseTimes::GCParPhases coderoots_phase,
+ G1GCPhaseTimes::GCParPhases objcopy_phase);
// Refine the card corresponding to "card_ptr". Safe to be called concurrently
// to the mutator.
void refine_card_concurrently(CardValue* card_ptr,
uint worker_i);
- // Refine the card corresponding to "card_ptr", applying the given closure to
- // all references found. Must only be called during gc.
- // Returns whether the card has been scanned.
- bool refine_card_during_gc(CardValue* card_ptr, G1ScanCardClosure* update_rs_cl);
-
// Print accumulated summary info from the start of the VM.
void print_summary_info();
--- a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -35,12 +35,10 @@
G1SATBMarkQueueSet::G1SATBMarkQueueSet() : _g1h(NULL) {}
void G1SATBMarkQueueSet::initialize(G1CollectedHeap* g1h,
- Monitor* cbl_mon,
BufferNode::Allocator* allocator,
size_t process_completed_buffers_threshold,
uint buffer_enqueue_threshold_percentage) {
- SATBMarkQueueSet::initialize(cbl_mon,
- allocator,
+ SATBMarkQueueSet::initialize(allocator,
process_completed_buffers_threshold,
buffer_enqueue_threshold_percentage);
_g1h = g1h;
--- a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -38,7 +38,6 @@
G1SATBMarkQueueSet();
void initialize(G1CollectedHeap* g1h,
- Monitor* cbl_mon,
BufferNode::Allocator* allocator,
size_t process_completed_buffers_threshold,
uint buffer_enqueue_threshold_percentage);
--- a/src/hotspot/share/gc/g1/heapRegion.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -49,6 +49,7 @@
int HeapRegion::LogOfHRGrainBytes = 0;
int HeapRegion::LogOfHRGrainWords = 0;
+int HeapRegion::LogCardsPerRegion = 0;
size_t HeapRegion::GrainBytes = 0;
size_t HeapRegion::GrainWords = 0;
size_t HeapRegion::CardsPerRegion = 0;
@@ -105,6 +106,8 @@
guarantee(CardsPerRegion == 0, "we should only set it once");
CardsPerRegion = GrainBytes >> G1CardTable::card_shift;
+ LogCardsPerRegion = log2_long((jlong) CardsPerRegion);
+
if (G1HeapRegionSize != GrainBytes) {
FLAG_SET_ERGO(G1HeapRegionSize, GrainBytes);
}
--- a/src/hotspot/share/gc/g1/heapRegion.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -60,7 +60,6 @@
class G1CMBitMap;
class G1IsAliveAndApplyClosure;
class HeapRegionRemSet;
-class HeapRegionRemSetIterator;
class HeapRegion;
class HeapRegionSetBase;
class nmethod;
@@ -315,6 +314,7 @@
static int LogOfHRGrainBytes;
static int LogOfHRGrainWords;
+ static int LogCardsPerRegion;
static size_t GrainBytes;
static size_t GrainWords;
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -27,7 +27,7 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
-#include "gc/g1/heapRegionRemSet.hpp"
+#include "gc/g1/heapRegionRemSet.inline.hpp"
#include "gc/shared/space.inline.hpp"
#include "memory/allocation.hpp"
#include "memory/padded.inline.hpp"
@@ -42,195 +42,21 @@
const char* HeapRegionRemSet::_state_strings[] = {"Untracked", "Updating", "Complete"};
const char* HeapRegionRemSet::_short_state_strings[] = {"UNTRA", "UPDAT", "CMPLT"};
-class PerRegionTable: public CHeapObj<mtGC> {
- friend class OtherRegionsTable;
- friend class HeapRegionRemSetIterator;
-
- HeapRegion* _hr;
- CHeapBitMap _bm;
- jint _occupied;
-
- // next pointer for free/allocated 'all' list
- PerRegionTable* _next;
-
- // prev pointer for the allocated 'all' list
- PerRegionTable* _prev;
-
- // next pointer in collision list
- PerRegionTable * _collision_list_next;
-
- // Global free list of PRTs
- static PerRegionTable* volatile _free_list;
-
-protected:
- // We need access in order to union things into the base table.
- BitMap* bm() { return &_bm; }
-
- PerRegionTable(HeapRegion* hr) :
- _hr(hr),
- _bm(HeapRegion::CardsPerRegion, mtGC),
- _occupied(0),
- _next(NULL), _prev(NULL),
- _collision_list_next(NULL)
- {}
-
- void add_card_work(CardIdx_t from_card, bool par) {
- if (!_bm.at(from_card)) {
- if (par) {
- if (_bm.par_at_put(from_card, 1)) {
- Atomic::inc(&_occupied);
- }
- } else {
- _bm.at_put(from_card, 1);
- _occupied++;
- }
- }
- }
-
- void add_reference_work(OopOrNarrowOopStar from, bool par) {
- // Must make this robust in case "from" is not in "_hr", because of
- // concurrency.
-
- HeapRegion* loc_hr = hr();
- // If the test below fails, then this table was reused concurrently
- // with this operation. This is OK, since the old table was coarsened,
- // and adding a bit to the new table is never incorrect.
- if (loc_hr->is_in_reserved(from)) {
- CardIdx_t from_card = OtherRegionsTable::card_within_region(from, loc_hr);
- add_card_work(from_card, par);
+PerRegionTable* PerRegionTable::alloc(HeapRegion* hr) {
+ PerRegionTable* fl = _free_list;
+ while (fl != NULL) {
+ PerRegionTable* nxt = fl->next();
+ PerRegionTable* res = Atomic::cmpxchg(nxt, &_free_list, fl);
+ if (res == fl) {
+ fl->init(hr, true);
+ return fl;
+ } else {
+ fl = _free_list;
}
}
-
-public:
-
- HeapRegion* hr() const { return OrderAccess::load_acquire(&_hr); }
-
- jint occupied() const {
- // Overkill, but if we ever need it...
- // guarantee(_occupied == _bm.count_one_bits(), "Check");
- return _occupied;
- }
-
- void init(HeapRegion* hr, bool clear_links_to_all_list) {
- if (clear_links_to_all_list) {
- set_next(NULL);
- set_prev(NULL);
- }
- _collision_list_next = NULL;
- _occupied = 0;
- _bm.clear();
- // Make sure that the bitmap clearing above has been finished before publishing
- // this PRT to concurrent threads.
- OrderAccess::release_store(&_hr, hr);
- }
-
- void add_reference(OopOrNarrowOopStar from) {
- add_reference_work(from, /*parallel*/ true);
- }
-
- void seq_add_reference(OopOrNarrowOopStar from) {
- add_reference_work(from, /*parallel*/ false);
- }
-
- void add_card(CardIdx_t from_card_index) {
- add_card_work(from_card_index, /*parallel*/ true);
- }
-
- void seq_add_card(CardIdx_t from_card_index) {
- add_card_work(from_card_index, /*parallel*/ false);
- }
-
- // (Destructively) union the bitmap of the current table into the given
- // bitmap (which is assumed to be of the same size.)
- void union_bitmap_into(BitMap* bm) {
- bm->set_union(_bm);
- }
-
- // Mem size in bytes.
- size_t mem_size() const {
- return sizeof(PerRegionTable) + _bm.size_in_words() * HeapWordSize;
- }
-
- // Requires "from" to be in "hr()".
- bool contains_reference(OopOrNarrowOopStar from) const {
- assert(hr()->is_in_reserved(from), "Precondition.");
- size_t card_ind = pointer_delta(from, hr()->bottom(),
- G1CardTable::card_size);
- return _bm.at(card_ind);
- }
-
- // Bulk-free the PRTs from prt to last, assumes that they are
- // linked together using their _next field.
- static void bulk_free(PerRegionTable* prt, PerRegionTable* last) {
- while (true) {
- PerRegionTable* fl = _free_list;
- last->set_next(fl);
- PerRegionTable* res = Atomic::cmpxchg(prt, &_free_list, fl);
- if (res == fl) {
- return;
- }
- }
- ShouldNotReachHere();
- }
-
- static void free(PerRegionTable* prt) {
- bulk_free(prt, prt);
- }
-
- // Returns an initialized PerRegionTable instance.
- static PerRegionTable* alloc(HeapRegion* hr) {
- PerRegionTable* fl = _free_list;
- while (fl != NULL) {
- PerRegionTable* nxt = fl->next();
- PerRegionTable* res = Atomic::cmpxchg(nxt, &_free_list, fl);
- if (res == fl) {
- fl->init(hr, true);
- return fl;
- } else {
- fl = _free_list;
- }
- }
- assert(fl == NULL, "Loop condition.");
- return new PerRegionTable(hr);
- }
-
- PerRegionTable* next() const { return _next; }
- void set_next(PerRegionTable* next) { _next = next; }
- PerRegionTable* prev() const { return _prev; }
- void set_prev(PerRegionTable* prev) { _prev = prev; }
-
- // Accessor and Modification routines for the pointer for the
- // singly linked collision list that links the PRTs within the
- // OtherRegionsTable::_fine_grain_regions hash table.
- //
- // It might be useful to also make the collision list doubly linked
- // to avoid iteration over the collisions list during scrubbing/deletion.
- // OTOH there might not be many collisions.
-
- PerRegionTable* collision_list_next() const {
- return _collision_list_next;
- }
-
- void set_collision_list_next(PerRegionTable* next) {
- _collision_list_next = next;
- }
-
- PerRegionTable** collision_list_next_addr() {
- return &_collision_list_next;
- }
-
- static size_t fl_mem_size() {
- PerRegionTable* cur = _free_list;
- size_t res = 0;
- while (cur != NULL) {
- res += cur->mem_size();
- cur = cur->next();
- }
- return res;
- }
-
- static void test_fl_mem_size();
-};
+ assert(fl == NULL, "Loop condition.");
+ return new PerRegionTable(hr);
+}
PerRegionTable* volatile PerRegionTable::_free_list = NULL;
@@ -696,175 +522,3 @@
size_t HeapRegionRemSet::strong_code_roots_mem_size() {
return _code_roots.mem_size();
}
-
-HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) :
- _hrrs(hrrs),
- _coarse_map(&hrrs->_other_regions._coarse_map),
- _bot(hrrs->_bot),
- _g1h(G1CollectedHeap::heap()),
- _n_yielded_fine(0),
- _n_yielded_coarse(0),
- _n_yielded_sparse(0),
- _is(Sparse),
- _cur_region_card_offset(0),
- // Set these values so that we increment to the first region.
- _coarse_cur_region_index(-1),
- _coarse_cur_region_cur_card(HeapRegion::CardsPerRegion-1),
- _fine_cur_prt(NULL),
- _cur_card_in_prt(HeapRegion::CardsPerRegion),
- _sparse_iter(&hrrs->_other_regions._sparse_table) {}
-
-bool HeapRegionRemSetIterator::coarse_has_next(size_t& card_index) {
- if (_hrrs->_other_regions._n_coarse_entries == 0) return false;
- // Go to the next card.
- _coarse_cur_region_cur_card++;
- // Was the last the last card in the current region?
- if (_coarse_cur_region_cur_card == HeapRegion::CardsPerRegion) {
- // Yes: find the next region. This may leave _coarse_cur_region_index
- // Set to the last index, in which case there are no more coarse
- // regions.
- _coarse_cur_region_index =
- (int) _coarse_map->get_next_one_offset(_coarse_cur_region_index + 1);
- if ((size_t)_coarse_cur_region_index < _coarse_map->size()) {
- _coarse_cur_region_cur_card = 0;
- HeapWord* r_bot =
- _g1h->region_at((uint) _coarse_cur_region_index)->bottom();
- _cur_region_card_offset = _bot->index_for_raw(r_bot);
- } else {
- return false;
- }
- }
- // If we didn't return false above, then we can yield a card.
- card_index = _cur_region_card_offset + _coarse_cur_region_cur_card;
- return true;
-}
-
-bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) {
- if (fine_has_next()) {
- _cur_card_in_prt =
- _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1);
- }
- if (_cur_card_in_prt == HeapRegion::CardsPerRegion) {
- // _fine_cur_prt may still be NULL in case if there are not PRTs at all for
- // the remembered set.
- if (_fine_cur_prt == NULL || _fine_cur_prt->next() == NULL) {
- return false;
- }
- PerRegionTable* next_prt = _fine_cur_prt->next();
- switch_to_prt(next_prt);
- _cur_card_in_prt = _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1);
- }
-
- card_index = _cur_region_card_offset + _cur_card_in_prt;
- guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion,
- "Card index " SIZE_FORMAT " must be within the region", _cur_card_in_prt);
- return true;
-}
-
-bool HeapRegionRemSetIterator::fine_has_next() {
- return _cur_card_in_prt != HeapRegion::CardsPerRegion;
-}
-
-void HeapRegionRemSetIterator::switch_to_prt(PerRegionTable* prt) {
- assert(prt != NULL, "Cannot switch to NULL prt");
- _fine_cur_prt = prt;
-
- HeapWord* r_bot = _fine_cur_prt->hr()->bottom();
- _cur_region_card_offset = _bot->index_for_raw(r_bot);
-
- // The bitmap scan for the PRT always scans from _cur_region_cur_card + 1.
- // To avoid special-casing this start case, and not miss the first bitmap
- // entry, initialize _cur_region_cur_card with -1 instead of 0.
- _cur_card_in_prt = (size_t)-1;
-}
-
-bool HeapRegionRemSetIterator::has_next(size_t& card_index) {
- switch (_is) {
- case Sparse: {
- if (_sparse_iter.has_next(card_index)) {
- _n_yielded_sparse++;
- return true;
- }
- // Otherwise, deliberate fall-through
- _is = Fine;
- PerRegionTable* initial_fine_prt = _hrrs->_other_regions._first_all_fine_prts;
- if (initial_fine_prt != NULL) {
- switch_to_prt(_hrrs->_other_regions._first_all_fine_prts);
- }
- }
- case Fine:
- if (fine_has_next(card_index)) {
- _n_yielded_fine++;
- return true;
- }
- // Otherwise, deliberate fall-through
- _is = Coarse;
- case Coarse:
- if (coarse_has_next(card_index)) {
- _n_yielded_coarse++;
- return true;
- }
- // Otherwise...
- break;
- }
- return false;
-}
-
-#ifndef PRODUCT
-void HeapRegionRemSet::test() {
- os::sleep(Thread::current(), (jlong)5000, false);
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
- // Run with "-XX:G1LogRSetRegionEntries=2", so that 1 and 5 end up in same
- // hash bucket.
- HeapRegion* hr0 = g1h->region_at(0);
- HeapRegion* hr1 = g1h->region_at(1);
- HeapRegion* hr2 = g1h->region_at(5);
- HeapRegion* hr3 = g1h->region_at(6);
- HeapRegion* hr4 = g1h->region_at(7);
- HeapRegion* hr5 = g1h->region_at(8);
-
- HeapWord* hr1_start = hr1->bottom();
- HeapWord* hr1_mid = hr1_start + HeapRegion::GrainWords/2;
- HeapWord* hr1_last = hr1->end() - 1;
-
- HeapWord* hr2_start = hr2->bottom();
- HeapWord* hr2_mid = hr2_start + HeapRegion::GrainWords/2;
- HeapWord* hr2_last = hr2->end() - 1;
-
- HeapWord* hr3_start = hr3->bottom();
- HeapWord* hr3_mid = hr3_start + HeapRegion::GrainWords/2;
- HeapWord* hr3_last = hr3->end() - 1;
-
- HeapRegionRemSet* hrrs = hr0->rem_set();
-
- // Make three references from region 0x101...
- hrrs->add_reference((OopOrNarrowOopStar)hr1_start);
- hrrs->add_reference((OopOrNarrowOopStar)hr1_mid);
- hrrs->add_reference((OopOrNarrowOopStar)hr1_last);
-
- hrrs->add_reference((OopOrNarrowOopStar)hr2_start);
- hrrs->add_reference((OopOrNarrowOopStar)hr2_mid);
- hrrs->add_reference((OopOrNarrowOopStar)hr2_last);
-
- hrrs->add_reference((OopOrNarrowOopStar)hr3_start);
- hrrs->add_reference((OopOrNarrowOopStar)hr3_mid);
- hrrs->add_reference((OopOrNarrowOopStar)hr3_last);
-
- // Now cause a coarsening.
- hrrs->add_reference((OopOrNarrowOopStar)hr4->bottom());
- hrrs->add_reference((OopOrNarrowOopStar)hr5->bottom());
-
- // Now, does iteration yield these three?
- HeapRegionRemSetIterator iter(hrrs);
- size_t sum = 0;
- size_t card_index;
- while (iter.has_next(card_index)) {
- HeapWord* card_start = g1h->bot()->address_for_index(card_index);
- tty->print_cr(" Card " PTR_FORMAT ".", p2i(card_start));
- sum++;
- }
- guarantee(sum == 11 - 3 + 2048, "Failure");
- guarantee(sum == hrrs->occupied(), "Failure");
-}
-#endif
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -28,6 +28,7 @@
#include "gc/g1/g1CodeCacheRemSet.hpp"
#include "gc/g1/g1FromCardCache.hpp"
#include "gc/g1/sparsePRT.hpp"
+#include "utilities/bitMap.hpp"
// Remembered set for a heap region. Represent a set of "cards" that
// contain pointers into the owner heap region. Cards are defined somewhat
@@ -37,7 +38,6 @@
class G1BlockOffsetTable;
class G1CardLiveData;
class HeapRegion;
-class HeapRegionRemSetIterator;
class PerRegionTable;
class SparsePRT;
class nmethod;
@@ -67,8 +67,6 @@
// thinking the PRT is for a different region, does no harm.
class OtherRegionsTable {
- friend class HeapRegionRemSetIterator;
-
G1CollectedHeap* _g1h;
Mutex* _m;
@@ -125,6 +123,9 @@
// Create a new remembered set. The given mutex is used to ensure consistency.
OtherRegionsTable(Mutex* m);
+ template <class Closure>
+ void iterate(Closure& v);
+
// Returns the card index of the given within_region pointer relative to the bottom
// of the given heap region.
static CardIdx_t card_within_region(OopOrNarrowOopStar within_region, HeapRegion* hr);
@@ -157,9 +158,140 @@
void clear();
};
+class PerRegionTable: public CHeapObj<mtGC> {
+ friend class OtherRegionsTable;
+
+ HeapRegion* _hr;
+ CHeapBitMap _bm;
+ jint _occupied;
+
+ // next pointer for free/allocated 'all' list
+ PerRegionTable* _next;
+
+ // prev pointer for the allocated 'all' list
+ PerRegionTable* _prev;
+
+ // next pointer in collision list
+ PerRegionTable * _collision_list_next;
+
+ // Global free list of PRTs
+ static PerRegionTable* volatile _free_list;
+
+protected:
+ PerRegionTable(HeapRegion* hr) :
+ _hr(hr),
+ _bm(HeapRegion::CardsPerRegion, mtGC),
+ _occupied(0),
+ _next(NULL), _prev(NULL),
+ _collision_list_next(NULL)
+ {}
+
+ inline void add_card_work(CardIdx_t from_card, bool par);
+
+ inline void add_reference_work(OopOrNarrowOopStar from, bool par);
+
+public:
+ // We need access in order to union things into the base table.
+ BitMap* bm() { return &_bm; }
+
+ HeapRegion* hr() const { return OrderAccess::load_acquire(&_hr); }
+
+ jint occupied() const {
+ // Overkill, but if we ever need it...
+ // guarantee(_occupied == _bm.count_one_bits(), "Check");
+ return _occupied;
+ }
+
+ void init(HeapRegion* hr, bool clear_links_to_all_list);
+
+ inline void add_reference(OopOrNarrowOopStar from);
+
+ inline void seq_add_reference(OopOrNarrowOopStar from);
+
+ inline void add_card(CardIdx_t from_card_index);
+
+ void seq_add_card(CardIdx_t from_card_index);
+
+ // (Destructively) union the bitmap of the current table into the given
+ // bitmap (which is assumed to be of the same size.)
+ void union_bitmap_into(BitMap* bm) {
+ bm->set_union(_bm);
+ }
+
+ // Mem size in bytes.
+ size_t mem_size() const {
+ return sizeof(PerRegionTable) + _bm.size_in_words() * HeapWordSize;
+ }
+
+ // Requires "from" to be in "hr()".
+ bool contains_reference(OopOrNarrowOopStar from) const {
+ assert(hr()->is_in_reserved(from), "Precondition.");
+ size_t card_ind = pointer_delta(from, hr()->bottom(),
+ G1CardTable::card_size);
+ return _bm.at(card_ind);
+ }
+
+ // Bulk-free the PRTs from prt to last, assumes that they are
+ // linked together using their _next field.
+ static void bulk_free(PerRegionTable* prt, PerRegionTable* last) {
+ while (true) {
+ PerRegionTable* fl = _free_list;
+ last->set_next(fl);
+ PerRegionTable* res = Atomic::cmpxchg(prt, &_free_list, fl);
+ if (res == fl) {
+ return;
+ }
+ }
+ ShouldNotReachHere();
+ }
+
+ static void free(PerRegionTable* prt) {
+ bulk_free(prt, prt);
+ }
+
+ // Returns an initialized PerRegionTable instance.
+ static PerRegionTable* alloc(HeapRegion* hr);
+
+ PerRegionTable* next() const { return _next; }
+ void set_next(PerRegionTable* next) { _next = next; }
+ PerRegionTable* prev() const { return _prev; }
+ void set_prev(PerRegionTable* prev) { _prev = prev; }
+
+ // Accessor and Modification routines for the pointer for the
+ // singly linked collision list that links the PRTs within the
+ // OtherRegionsTable::_fine_grain_regions hash table.
+ //
+ // It might be useful to also make the collision list doubly linked
+ // to avoid iteration over the collisions list during scrubbing/deletion.
+ // OTOH there might not be many collisions.
+
+ PerRegionTable* collision_list_next() const {
+ return _collision_list_next;
+ }
+
+ void set_collision_list_next(PerRegionTable* next) {
+ _collision_list_next = next;
+ }
+
+ PerRegionTable** collision_list_next_addr() {
+ return &_collision_list_next;
+ }
+
+ static size_t fl_mem_size() {
+ PerRegionTable* cur = _free_list;
+ size_t res = 0;
+ while (cur != NULL) {
+ res += cur->mem_size();
+ cur = cur->next();
+ }
+ return res;
+ }
+
+ static void test_fl_mem_size();
+};
+
class HeapRegionRemSet : public CHeapObj<mtGC> {
friend class VMStructs;
- friend class HeapRegionRemSetIterator;
private:
G1BlockOffsetTable* _bot;
@@ -182,18 +314,23 @@
// Setup sparse and fine-grain tables sizes.
static void setup_remset_size();
- bool cardset_is_empty() const {
- return _other_regions.is_empty();
- }
-
bool is_empty() const {
- return (strong_code_roots_list_length() == 0) && cardset_is_empty();
+ return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
}
bool occupancy_less_or_equal_than(size_t occ) const {
return (strong_code_roots_list_length() == 0) && _other_regions.occupancy_less_or_equal_than(occ);
}
+ // For each PRT in the card (remembered) set call one of the following methods
+ // of the given closure:
+ //
+ // set_full_region_dirty(uint region_idx) - pass the region index for coarse PRTs
+ // set_bitmap_dirty(uint region_idx, BitMap* bitmap) - pass the region index and bitmap for fine PRTs
+ // set_cards_dirty(uint region_idx, elem_t* cards, uint num_cards) - pass region index and cards for sparse PRTs
+ template <class Closure>
+ inline void iterate_prts(Closure& cl);
+
size_t occupied() {
MutexLocker x(&_m, Mutex::_no_safepoint_check_flag);
return occupied_locked();
@@ -339,70 +476,4 @@
#endif
};
-class HeapRegionRemSetIterator : public StackObj {
-private:
- // The region RSet over which we are iterating.
- HeapRegionRemSet* _hrrs;
-
- // Local caching of HRRS fields.
- const BitMap* _coarse_map;
-
- G1BlockOffsetTable* _bot;
- G1CollectedHeap* _g1h;
-
- // The number of cards yielded since initialization.
- size_t _n_yielded_fine;
- size_t _n_yielded_coarse;
- size_t _n_yielded_sparse;
-
- // Indicates what granularity of table that we are currently iterating over.
- // We start iterating over the sparse table, progress to the fine grain
- // table, and then finish with the coarse table.
- enum IterState {
- Sparse,
- Fine,
- Coarse
- };
- IterState _is;
-
- // For both Coarse and Fine remembered set iteration this contains the
- // first card number of the heap region we currently iterate over.
- size_t _cur_region_card_offset;
-
- // Current region index for the Coarse remembered set iteration.
- int _coarse_cur_region_index;
- size_t _coarse_cur_region_cur_card;
-
- bool coarse_has_next(size_t& card_index);
-
- // The PRT we are currently iterating over.
- PerRegionTable* _fine_cur_prt;
- // Card offset within the current PRT.
- size_t _cur_card_in_prt;
-
- // Update internal variables when switching to the given PRT.
- void switch_to_prt(PerRegionTable* prt);
- bool fine_has_next();
- bool fine_has_next(size_t& card_index);
-
- // The Sparse remembered set iterator.
- SparsePRTIter _sparse_iter;
-
-public:
- HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
-
- // If there remains one or more cards to be yielded, returns true and
- // sets "card_index" to one of those cards (which is then considered
- // yielded.) Otherwise, returns false (and leaves "card_index"
- // undefined.)
- bool has_next(size_t& card_index);
-
- size_t n_yielded_fine() { return _n_yielded_fine; }
- size_t n_yielded_coarse() { return _n_yielded_coarse; }
- size_t n_yielded_sparse() { return _n_yielded_sparse; }
- size_t n_yielded() {
- return n_yielded_fine() + n_yielded_coarse() + n_yielded_sparse();
- }
-};
-
#endif // SHARE_GC_G1_HEAPREGIONREMSET_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP
+#define SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP
+
+#include "gc/g1/heapRegion.inline.hpp"
+#include "gc/g1/heapRegionRemSet.hpp"
+#include "gc/g1/sparsePRT.hpp"
+#include "utilities/bitMap.inline.hpp"
+
+template <class Closure>
+inline void HeapRegionRemSet::iterate_prts(Closure& cl) {
+ _other_regions.iterate(cl);
+}
+
+inline void PerRegionTable::add_card_work(CardIdx_t from_card, bool par) {
+ if (!_bm.at(from_card)) {
+ if (par) {
+ if (_bm.par_set_bit(from_card)) {
+ Atomic::inc(&_occupied);
+ }
+ } else {
+ _bm.set_bit(from_card);
+ _occupied++;
+ }
+ }
+}
+
+inline void PerRegionTable::add_reference_work(OopOrNarrowOopStar from, bool par) {
+ // Must make this robust in case "from" is not in "_hr", because of
+ // concurrency.
+
+ HeapRegion* loc_hr = hr();
+ // If the test below fails, then this table was reused concurrently
+ // with this operation. This is OK, since the old table was coarsened,
+ // and adding a bit to the new table is never incorrect.
+ if (loc_hr->is_in_reserved(from)) {
+ CardIdx_t from_card = OtherRegionsTable::card_within_region(from, loc_hr);
+ add_card_work(from_card, par);
+ }
+}
+
+inline void PerRegionTable::add_card(CardIdx_t from_card_index) {
+ add_card_work(from_card_index, /*parallel*/ true);
+}
+
+inline void PerRegionTable::seq_add_card(CardIdx_t from_card_index) {
+ add_card_work(from_card_index, /*parallel*/ false);
+}
+
+inline void PerRegionTable::add_reference(OopOrNarrowOopStar from) {
+ add_reference_work(from, /*parallel*/ true);
+}
+
+inline void PerRegionTable::seq_add_reference(OopOrNarrowOopStar from) {
+ add_reference_work(from, /*parallel*/ false);
+}
+
+inline void PerRegionTable::init(HeapRegion* hr, bool clear_links_to_all_list) {
+ if (clear_links_to_all_list) {
+ set_next(NULL);
+ set_prev(NULL);
+ }
+ _collision_list_next = NULL;
+ _occupied = 0;
+ _bm.clear();
+ // Make sure that the bitmap clearing above has been finished before publishing
+ // this PRT to concurrent threads.
+ OrderAccess::release_store(&_hr, hr);
+}
+
+template <class Closure>
+void OtherRegionsTable::iterate(Closure& cl) {
+ if (_n_coarse_entries > 0) {
+ BitMap::idx_t cur = _coarse_map.get_next_one_offset(0);
+ while (cur != _coarse_map.size()) {
+ cl.next_coarse_prt((uint)cur);
+ cur = _coarse_map.get_next_one_offset(cur + 1);
+ }
+ }
+ {
+ PerRegionTable* cur = _first_all_fine_prts;
+ while (cur != NULL) {
+ cl.next_fine_prt(cur->hr()->hrm_index(), cur->bm());
+ cur = cur->next();
+ }
+ }
+ {
+ SparsePRTBucketIter iter(&_sparse_table);
+ SparsePRTEntry* cur;
+ while (iter.has_next(cur)) {
+ cl.next_sparse_prt(cur->r_ind(), cur->cards(), cur->num_valid_cards());
+ }
+ }
+}
+
+#endif // SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP
--- a/src/hotspot/share/gc/g1/sparsePRT.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/sparsePRT.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -275,6 +275,19 @@
return false;
}
+bool RSHashTableBucketIter::has_next(SparsePRTEntry*& entry) {
+ while (_bl_ind == RSHashTable::NullEntry) {
+ if (_tbl_ind == (int)_rsht->capacity() - 1) {
+ return false;
+ }
+ _tbl_ind++;
+ _bl_ind = _rsht->_buckets[_tbl_ind];
+ }
+ entry = _rsht->entry(_bl_ind);
+ _bl_ind = entry->next_index();
+ return true;
+}
+
bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const {
SparsePRTEntry* e = get_entry(region_index);
return (e != NULL && e->contains_card(card_index));
--- a/src/hotspot/share/gc/g1/sparsePRT.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/g1/sparsePRT.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -38,10 +38,11 @@
// that might contain pointers into the owner region.
class SparsePRTEntry: public CHeapObj<mtGC> {
-private:
+public:
// The type of a card entry.
typedef uint16_t card_elem_t;
+private:
// We need to make sizeof(SparsePRTEntry) an even multiple of maximum member size,
// in order to force correct alignment that could otherwise cause SIGBUS errors
// when reading the member variables. This calculates the minimum number of card
@@ -96,6 +97,8 @@
// Copy the current entry's cards into the "_card" array of "e."
inline void copy_cards(SparsePRTEntry* e) const;
+ card_elem_t* cards() { return _cards; }
+
inline CardIdx_t card(int i) const {
assert(i >= 0, "must be nonnegative");
assert(i < cards_num(), "range checking");
@@ -106,7 +109,7 @@
class RSHashTable : public CHeapObj<mtGC> {
friend class RSHashTableIter;
-
+ friend class RSHashTableBucketIter;
// Inverse maximum hash table occupancy used.
static float TableOccupancyFactor;
@@ -209,12 +212,29 @@
bool has_next(size_t& card_index);
};
+// This is embedded in HRRS iterator.
+class RSHashTableBucketIter {
+ int _tbl_ind; // [-1, 0.._rsht->_capacity)
+ int _bl_ind; // [-1, 0.._rsht->_capacity)
+
+ RSHashTable* _rsht;
+
+public:
+ RSHashTableBucketIter(RSHashTable* rsht) :
+ _tbl_ind(0),
+ _bl_ind(rsht->_buckets[_tbl_ind]),
+ _rsht(rsht) { }
+
+ bool has_next(SparsePRTEntry*& entry);
+};
+
// Concurrent access to a SparsePRT must be serialized by some external mutex.
class SparsePRTIter;
class SparsePRT {
friend class SparsePRTIter;
+ friend class SparsePRTBucketIter;
RSHashTable* _table;
@@ -262,4 +282,14 @@
}
};
+class SparsePRTBucketIter: public RSHashTableBucketIter {
+public:
+ SparsePRTBucketIter(const SparsePRT* sprt) :
+ RSHashTableBucketIter(sprt->_table) {}
+
+ bool has_next(SparsePRTEntry*& entry) {
+ return RSHashTableBucketIter::has_next(entry);
+ }
+};
+
#endif // SHARE_GC_G1_SPARSEPRT_HPP
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -259,7 +259,6 @@
BiasedLocking::restore_marks();
heap->prune_scavengable_nmethods();
- JvmtiExport::gc_epilogue();
#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -1064,7 +1064,6 @@
MetaspaceUtils::verify_metrics();
heap->prune_scavengable_nmethods();
- JvmtiExport::gc_epilogue();
#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -129,7 +129,6 @@
}
gch->prune_scavengable_nmethods();
- JvmtiExport::gc_epilogue();
// refs processing: clean slate
set_ref_processor(NULL);
--- a/src/hotspot/share/gc/shared/cardTable.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shared/cardTable.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -103,15 +103,11 @@
enum CardValues {
clean_card = (CardValue)-1,
- // The mask contains zeros in places for all other values.
- clean_card_mask = clean_card - 31,
dirty_card = 0,
precleaned_card = 1,
- claimed_card = 2,
- deferred_card = 4,
- last_card = 8,
- CT_MR_BS_last_reserved = 16
+ last_card = 2,
+ CT_MR_BS_last_reserved = 4
};
// a word's worth (row) of clean card values
@@ -242,11 +238,8 @@
};
static CardValue clean_card_val() { return clean_card; }
- static CardValue clean_card_mask_val() { return clean_card_mask; }
static CardValue dirty_card_val() { return dirty_card; }
- static CardValue claimed_card_val() { return claimed_card; }
static CardValue precleaned_card_val() { return precleaned_card; }
- static CardValue deferred_card_val() { return deferred_card; }
static intptr_t clean_card_row_val() { return clean_card_row; }
// Card marking array base (adjusted for heap low boundary)
--- a/src/hotspot/share/gc/shared/ptrQueue.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shared/ptrQueue.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -250,28 +250,15 @@
return removed;
}
-PtrQueueSet::PtrQueueSet(bool notify_when_complete) :
+PtrQueueSet::PtrQueueSet() :
_allocator(NULL),
- _cbl_mon(NULL),
- _completed_buffers_head(NULL),
- _completed_buffers_tail(NULL),
- _n_completed_buffers(0),
- _process_completed_buffers_threshold(ProcessCompletedBuffersThresholdNever),
- _process_completed_buffers(false),
- _notify_when_complete(notify_when_complete),
_all_active(false)
{}
-PtrQueueSet::~PtrQueueSet() {
- // There are presently only a couple (derived) instances ever
- // created, and they are permanent, so no harm currently done by
- // doing nothing here.
-}
+PtrQueueSet::~PtrQueueSet() {}
-void PtrQueueSet::initialize(Monitor* cbl_mon,
- BufferNode::Allocator* allocator) {
- assert(cbl_mon != NULL && allocator != NULL, "Init order issue?");
- _cbl_mon = cbl_mon;
+void PtrQueueSet::initialize(BufferNode::Allocator* allocator) {
+ assert(allocator != NULL, "Init order issue?");
_allocator = allocator;
}
@@ -284,121 +271,3 @@
_allocator->release(node);
}
-void PtrQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
- MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- cbn->set_next(NULL);
- if (_completed_buffers_tail == NULL) {
- assert(_completed_buffers_head == NULL, "Well-formedness");
- _completed_buffers_head = cbn;
- _completed_buffers_tail = cbn;
- } else {
- _completed_buffers_tail->set_next(cbn);
- _completed_buffers_tail = cbn;
- }
- _n_completed_buffers++;
-
- if (!_process_completed_buffers &&
- (_n_completed_buffers > _process_completed_buffers_threshold)) {
- _process_completed_buffers = true;
- if (_notify_when_complete) {
- _cbl_mon->notify();
- }
- }
- assert_completed_buffers_list_len_correct_locked();
-}
-
-BufferNode* PtrQueueSet::get_completed_buffer(size_t stop_at) {
- MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
-
- if (_n_completed_buffers <= stop_at) {
- return NULL;
- }
-
- assert(_n_completed_buffers > 0, "invariant");
- assert(_completed_buffers_head != NULL, "invariant");
- assert(_completed_buffers_tail != NULL, "invariant");
-
- BufferNode* bn = _completed_buffers_head;
- _n_completed_buffers--;
- _completed_buffers_head = bn->next();
- if (_completed_buffers_head == NULL) {
- assert(_n_completed_buffers == 0, "invariant");
- _completed_buffers_tail = NULL;
- _process_completed_buffers = false;
- }
- assert_completed_buffers_list_len_correct_locked();
- bn->set_next(NULL);
- return bn;
-}
-
-void PtrQueueSet::abandon_completed_buffers() {
- BufferNode* buffers_to_delete = NULL;
- {
- MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- buffers_to_delete = _completed_buffers_head;
- _completed_buffers_head = NULL;
- _completed_buffers_tail = NULL;
- _n_completed_buffers = 0;
- _process_completed_buffers = false;
- }
- while (buffers_to_delete != NULL) {
- BufferNode* bn = buffers_to_delete;
- buffers_to_delete = bn->next();
- bn->set_next(NULL);
- deallocate_buffer(bn);
- }
-}
-
-#ifdef ASSERT
-
-void PtrQueueSet::assert_completed_buffers_list_len_correct_locked() {
- assert_lock_strong(_cbl_mon);
- size_t n = 0;
- for (BufferNode* bn = _completed_buffers_head; bn != NULL; bn = bn->next()) {
- ++n;
- }
- assert(n == _n_completed_buffers,
- "Completed buffer length is wrong: counted: " SIZE_FORMAT
- ", expected: " SIZE_FORMAT, n, _n_completed_buffers);
-}
-
-#endif // ASSERT
-
-// Merge lists of buffers. Notify the processing threads.
-// The source queue is emptied as a result. The queues
-// must share the monitor.
-void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) {
- assert(_cbl_mon == src->_cbl_mon, "Should share the same lock");
- MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- if (_completed_buffers_tail == NULL) {
- assert(_completed_buffers_head == NULL, "Well-formedness");
- _completed_buffers_head = src->_completed_buffers_head;
- _completed_buffers_tail = src->_completed_buffers_tail;
- } else {
- assert(_completed_buffers_head != NULL, "Well formedness");
- if (src->_completed_buffers_head != NULL) {
- _completed_buffers_tail->set_next(src->_completed_buffers_head);
- _completed_buffers_tail = src->_completed_buffers_tail;
- }
- }
- _n_completed_buffers += src->_n_completed_buffers;
-
- src->_n_completed_buffers = 0;
- src->_completed_buffers_head = NULL;
- src->_completed_buffers_tail = NULL;
- src->_process_completed_buffers = false;
-
- assert(_completed_buffers_head == NULL && _completed_buffers_tail == NULL ||
- _completed_buffers_head != NULL && _completed_buffers_tail != NULL,
- "Sanity");
- assert_completed_buffers_list_len_correct_locked();
-}
-
-void PtrQueueSet::notify_if_necessary() {
- MutexLocker x(_cbl_mon, Mutex::_no_safepoint_check_flag);
- if (_n_completed_buffers > _process_completed_buffers_threshold) {
- _process_completed_buffers = true;
- if (_notify_when_complete)
- _cbl_mon->notify();
- }
-}
--- a/src/hotspot/share/gc/shared/ptrQueue.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shared/ptrQueue.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -296,35 +296,16 @@
class PtrQueueSet {
BufferNode::Allocator* _allocator;
- Monitor* _cbl_mon; // Protects the fields below.
- BufferNode* _completed_buffers_head;
- BufferNode* _completed_buffers_tail;
- volatile size_t _n_completed_buffers;
-
- size_t _process_completed_buffers_threshold;
- volatile bool _process_completed_buffers;
-
- // If true, notify_all on _cbl_mon when the threshold is reached.
- bool _notify_when_complete;
-
- void assert_completed_buffers_list_len_correct_locked() NOT_DEBUG_RETURN;
-
protected:
bool _all_active;
// Create an empty ptr queue set.
- PtrQueueSet(bool notify_when_complete = false);
+ PtrQueueSet();
~PtrQueueSet();
// Because of init-order concerns, we can't pass these as constructor
// arguments.
- void initialize(Monitor* cbl_mon, BufferNode::Allocator* allocator);
-
- // For (unlocked!) iteration over the completed buffers.
- BufferNode* completed_buffers_head() const { return _completed_buffers_head; }
-
- // Deallocate all of the completed buffers.
- void abandon_completed_buffers();
+ void initialize(BufferNode::Allocator* allocator);
public:
@@ -339,38 +320,13 @@
// is ready to be processed by the collector. It need not be full.
// Adds node to the completed buffer list.
- void enqueue_completed_buffer(BufferNode* node);
-
- // If the number of completed buffers is > stop_at, then remove and
- // return a completed buffer from the list. Otherwise, return NULL.
- BufferNode* get_completed_buffer(size_t stop_at = 0);
-
- bool process_completed_buffers() { return _process_completed_buffers; }
- void set_process_completed_buffers(bool x) { _process_completed_buffers = x; }
+ virtual void enqueue_completed_buffer(BufferNode* node) = 0;
bool is_active() { return _all_active; }
size_t buffer_size() const {
return _allocator->buffer_size();
}
-
- // Get/Set the number of completed buffers that triggers log processing.
- // Log processing should be done when the number of buffers exceeds the
- // threshold.
- void set_process_completed_buffers_threshold(size_t sz) {
- _process_completed_buffers_threshold = sz;
- }
- size_t process_completed_buffers_threshold() const {
- return _process_completed_buffers_threshold;
- }
- static const size_t ProcessCompletedBuffersThresholdNever = ~size_t(0);
-
- size_t completed_buffers_num() const { return _n_completed_buffers; }
-
- void merge_bufferlists(PtrQueueSet* src);
-
- // Notify the consumer if the number of buffers crossed the threshold
- void notify_if_necessary();
};
#endif // SHARE_GC_SHARED_PTRQUEUE_HPP
--- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -28,12 +28,15 @@
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.hpp"
#include "runtime/os.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.hpp"
#include "runtime/threadSMR.hpp"
#include "runtime/vmThread.hpp"
+#include "utilities/globalCounter.inline.hpp"
SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset) :
// SATB queues are only active during marking cycles. We create
@@ -107,15 +110,66 @@
SATBMarkQueueSet::SATBMarkQueueSet() :
PtrQueueSet(),
+ _list(),
+ _count_and_process_flag(0),
+ _process_completed_buffers_threshold(SIZE_MAX),
_buffer_enqueue_threshold(0)
{}
-void SATBMarkQueueSet::initialize(Monitor* cbl_mon,
- BufferNode::Allocator* allocator,
+SATBMarkQueueSet::~SATBMarkQueueSet() {
+ abandon_completed_buffers();
+}
+
+// _count_and_process_flag has flag in least significant bit, count in
+// remaining bits. _process_completed_buffers_threshold is scaled
+// accordingly, with the lsbit set, so a _count_and_process_flag value
+// is directly comparable with the recorded threshold value. The
+// process flag is set whenever the count exceeds the threshold, and
+// remains set until the count is reduced to zero.
+
+// Increment count. If count > threshold, set flag, else maintain flag.
+static void increment_count(volatile size_t* cfptr, size_t threshold) {
+ size_t old;
+ size_t value = Atomic::load(cfptr);
+ do {
+ old = value;
+ value += 2;
+ assert(value > old, "overflow");
+ if (value > threshold) value |= 1;
+ value = Atomic::cmpxchg(value, cfptr, old);
+ } while (value != old);
+}
+
+// Decrement count. If count == 0, clear flag, else maintain flag.
+static void decrement_count(volatile size_t* cfptr) {
+ size_t old;
+ size_t value = Atomic::load(cfptr);
+ do {
+ assert((value >> 1) != 0, "underflow");
+ old = value;
+ value -= 2;
+ if (value <= 1) value = 0;
+ value = Atomic::cmpxchg(value, cfptr, old);
+ } while (value != old);
+}
+
+// Scale requested threshold to align with count field. If scaling
+// overflows, just use max value. Set process flag field to make
+// comparison in increment_count exact.
+static size_t scale_threshold(size_t value) {
+ size_t scaled_value = value << 1;
+ if ((scaled_value >> 1) != value) {
+ scaled_value = SIZE_MAX;
+ }
+ return scaled_value | 1;
+}
+
+void SATBMarkQueueSet::initialize(BufferNode::Allocator* allocator,
size_t process_completed_buffers_threshold,
uint buffer_enqueue_threshold_percentage) {
- PtrQueueSet::initialize(cbl_mon, allocator);
- set_process_completed_buffers_threshold(process_completed_buffers_threshold);
+ PtrQueueSet::initialize(allocator);
+ _process_completed_buffers_threshold =
+ scale_threshold(process_completed_buffers_threshold);
assert(buffer_size() != 0, "buffer size not initialized");
// Minimum threshold of 1 ensures enqueuing of completely full buffers.
size_t size = buffer_size();
@@ -207,6 +261,38 @@
}
}
+// SATB buffer life-cycle - Per-thread queues obtain buffers from the
+// qset's buffer allocator, fill them, and push them onto the qset's
+// list. The GC concurrently pops buffers from the qset, processes
+// them, and returns them to the buffer allocator for re-use. Both
+// the allocator and the qset use lock-free stacks. The ABA problem
+// is solved by having both allocation pops and GC pops performed
+// within GlobalCounter critical sections, while the return of buffers
+// to the allocator performs a GlobalCounter synchronize before
+// pushing onto the allocator's list.
+
+void SATBMarkQueueSet::enqueue_completed_buffer(BufferNode* node) {
+ assert(node != NULL, "precondition");
+ // Increment count and update flag appropriately. Done before
+ // pushing buffer so count is always at least the actual number in
+ // the list, and decrement never underflows.
+ increment_count(&_count_and_process_flag, _process_completed_buffers_threshold);
+ _list.push(*node);
+}
+
+BufferNode* SATBMarkQueueSet::get_completed_buffer() {
+ BufferNode* node;
+ {
+ GlobalCounter::CriticalSection cs(Thread::current());
+ node = _list.pop();
+ }
+ if (node != NULL) {
+ // Got a buffer so decrement count and update flag appropriately.
+ decrement_count(&_count_and_process_flag);
+ }
+ return node;
+}
+
#ifndef PRODUCT
// Helpful for debugging
@@ -219,7 +305,7 @@
tty->cr();
tty->print_cr("SATB BUFFERS [%s]", msg);
- BufferNode* nd = completed_buffers_head();
+ BufferNode* nd = _list.top();
int i = 0;
while (nd != NULL) {
void** buf = BufferNode::make_buffer_from_node(nd);
@@ -248,6 +334,17 @@
}
#endif // PRODUCT
+void SATBMarkQueueSet::abandon_completed_buffers() {
+ Atomic::store(size_t(0), &_count_and_process_flag);
+ BufferNode* buffers_to_delete = _list.pop_all();
+ while (buffers_to_delete != NULL) {
+ BufferNode* bn = buffers_to_delete;
+ buffers_to_delete = bn->next();
+ bn->set_next(NULL);
+ deallocate_buffer(bn);
+ }
+}
+
void SATBMarkQueueSet::abandon_partial_marking() {
assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
abandon_completed_buffers();
--- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -27,6 +27,7 @@
#include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.hpp"
+#include "memory/padded.hpp"
class Thread;
class Monitor;
@@ -93,7 +94,17 @@
};
class SATBMarkQueueSet: public PtrQueueSet {
+
+ DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0);
+ PaddedEnd<BufferNode::Stack> _list;
+ volatile size_t _count_and_process_flag;
+ // These are rarely (if ever) changed, so same cache line as count.
+ size_t _process_completed_buffers_threshold;
size_t _buffer_enqueue_threshold;
+ DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, 3 * sizeof(size_t));
+
+ BufferNode* get_completed_buffer();
+ void abandon_completed_buffers();
#ifdef ASSERT
void dump_active_states(bool expected_active);
@@ -102,15 +113,14 @@
protected:
SATBMarkQueueSet();
- ~SATBMarkQueueSet() {}
+ ~SATBMarkQueueSet();
template<typename Filter>
void apply_filter(Filter filter, SATBMarkQueue* queue) {
queue->apply_filter(filter);
}
- void initialize(Monitor* cbl_mon,
- BufferNode::Allocator* allocator,
+ void initialize(BufferNode::Allocator* allocator,
size_t process_completed_buffers_threshold,
uint buffer_enqueue_threshold_percentage);
@@ -132,6 +142,19 @@
// buffer; the leading entries may be excluded due to filtering.
bool apply_closure_to_completed_buffer(SATBBufferClosure* cl);
+ virtual void enqueue_completed_buffer(BufferNode* node);
+
+ // The number of buffers in the list. Racy and not updated atomically
+ // with the set of completed buffers.
+ size_t completed_buffers_num() const {
+ return _count_and_process_flag >> 1;
+ }
+
+ // Return true if completed buffers should be processed.
+ bool process_completed_buffers() const {
+ return (_count_and_process_flag & 1) != 0;
+ }
+
#ifndef PRODUCT
// Helpful for debugging
void print_all(const char* msg);
--- a/src/hotspot/share/gc/shared/workerDataArray.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shared/workerDataArray.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -34,7 +34,7 @@
class WorkerDataArray : public CHeapObj<mtGC> {
friend class WDAPrinter;
public:
- static const uint MaxThreadWorkItems = 5;
+ static const uint MaxThreadWorkItems = 6;
private:
T* _data;
uint _length;
--- a/src/hotspot/share/gc/shared/workerDataArray.inline.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shared/workerDataArray.inline.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -101,7 +101,7 @@
template <typename T>
void WorkerDataArray<T>::add(uint worker_i, T value) {
assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
- assert(_data[worker_i] != uninitialized(), "No data to add to for worker %d", worker_i);
+ assert(_data[worker_i] != uninitialized(), "No data to add to %s for worker %d", _title, worker_i);
_data[worker_i] += value;
}
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -348,7 +348,6 @@
// The call below uses stuff (the SATB* things) that are in G1, but probably
// belong into a shared location.
ShenandoahBarrierSet::satb_mark_queue_set().initialize(this,
- SATB_Q_CBL_mon,
20 /* G1SATBProcessCompletedThreshold */,
60 /* G1SATBBufferEnqueueingThresholdPercent */);
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -175,8 +175,6 @@
_preserved_marks->restore(&exec);
BiasedLocking::restore_marks();
_preserved_marks->reclaim();
-
- JvmtiExport::gc_epilogue();
}
// Resize metaspace
--- a/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -33,11 +33,9 @@
{}
void ShenandoahSATBMarkQueueSet::initialize(ShenandoahHeap* const heap,
- Monitor* cbl_mon,
int process_completed_threshold,
uint buffer_enqueue_threshold_percentage) {
- SATBMarkQueueSet::initialize(cbl_mon,
- &_satb_mark_queue_buffer_allocator,
+ SATBMarkQueueSet::initialize(&_satb_mark_queue_buffer_allocator,
process_completed_threshold,
buffer_enqueue_threshold_percentage);
_heap = heap;
--- a/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -44,7 +44,6 @@
ShenandoahSATBMarkQueueSet();
void initialize(ShenandoahHeap* const heap,
- Monitor* cbl_mon,
int process_completed_threshold,
uint buffer_enqueue_threshold_percentage);
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -198,7 +198,6 @@
} else {
ZNMethod::oops_do_end();
}
- JvmtiExport::gc_epilogue();
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
Threads::assert_all_threads_claimed();
--- a/src/hotspot/share/opto/type.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/opto/type.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -730,8 +730,11 @@
// Since we just discovered a new Type, compute its dual right now.
assert( !_dual, "" ); // No dual yet
_dual = xdual(); // Compute the dual
- if( cmp(this,_dual)==0 ) { // Handle self-symmetric
- _dual = this;
+ if (cmp(this, _dual) == 0) { // Handle self-symmetric
+ if (_dual != this) {
+ delete _dual;
+ _dual = this;
+ }
return this;
}
assert( !_dual->_dual, "" ); // No reverse dual yet
--- a/src/hotspot/share/prims/jvmtiExport.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/prims/jvmtiExport.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -2615,10 +2615,6 @@
JvmtiTagMap::weak_oops_do(is_alive, f);
}
-void JvmtiExport::gc_epilogue() {
- JvmtiCurrentBreakpoints::gc_epilogue();
-}
-
// Onload raw monitor transition.
void JvmtiExport::transition_pending_onload_raw_monitors() {
JvmtiPendingMonitors::transition_raw_monitors();
--- a/src/hotspot/share/prims/jvmtiExport.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/prims/jvmtiExport.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -388,7 +388,6 @@
static void oops_do(OopClosure* f) NOT_JVMTI_RETURN;
static void weak_oops_do(BoolObjectClosure* b, OopClosure* f) NOT_JVMTI_RETURN;
- static void gc_epilogue() NOT_JVMTI_RETURN;
static void transition_pending_onload_raw_monitors() NOT_JVMTI_RETURN;
--- a/src/hotspot/share/prims/jvmtiImpl.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -225,13 +225,6 @@
}
}
-void GrowableCache::gc_epilogue() {
- int len = _elements->length();
- for (int i=0; i<len; i++) {
- _cache[i] = _elements->at(i)->getCacheValue();
- }
-}
-
//
// class JvmtiBreakpoint
//
@@ -389,10 +382,6 @@
_bps.metadata_do(f);
}
-void JvmtiBreakpoints::gc_epilogue() {
- _bps.gc_epilogue();
-}
-
void JvmtiBreakpoints::print() {
#ifndef PRODUCT
LogTarget(Trace, jvmti) log;
@@ -514,12 +503,6 @@
}
}
-void JvmtiCurrentBreakpoints::gc_epilogue() {
- if (_jvmti_breakpoints != NULL) {
- _jvmti_breakpoints->gc_epilogue();
- }
-}
-
///////////////////////////////////////////////////////////////
//
// class VM_GetOrSetLocal
--- a/src/hotspot/share/prims/jvmtiImpl.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/prims/jvmtiImpl.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -120,8 +120,6 @@
void oops_do(OopClosure* f);
// walk metadata to preserve for RedefineClasses
void metadata_do(void f(Metadata*));
- // update the cache after a full gc
- void gc_epilogue();
};
@@ -154,7 +152,6 @@
void clear() { _cache.clear(); }
void oops_do(OopClosure* f) { _cache.oops_do(f); }
void metadata_do(void f(Metadata*)) { _cache.metadata_do(f); }
- void gc_epilogue() { _cache.gc_epilogue(); }
};
@@ -257,7 +254,6 @@
int set(JvmtiBreakpoint& bp);
int clear(JvmtiBreakpoint& bp);
void clearall_in_class_at_safepoint(Klass* klass);
- void gc_epilogue();
};
@@ -299,7 +295,6 @@
static void oops_do(OopClosure* f);
static void metadata_do(void f(Metadata*)) NOT_JVMTI_RETURN;
- static void gc_epilogue();
};
///////////////////////////////////////////////////////////////
--- a/src/hotspot/share/runtime/arguments.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/arguments.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -1815,6 +1815,10 @@
// was not specified.
if (reasonable_max > max_coop_heap) {
if (FLAG_IS_ERGO(UseCompressedOops) && override_coop_limit) {
+ log_info(cds)("UseCompressedOops and UseCompressedClassPointers have been disabled due to"
+ " max heap " SIZE_FORMAT " > compressed oop heap " SIZE_FORMAT ". "
+ "Please check the setting of MaxRAMPercentage %5.2f."
+ ,(size_t)reasonable_max, (size_t)max_coop_heap, MaxRAMPercentage);
FLAG_SET_ERGO(UseCompressedOops, false);
FLAG_SET_ERGO(UseCompressedClassPointers, false);
} else {
--- a/src/hotspot/share/runtime/biasedLocking.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/biasedLocking.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -548,7 +548,7 @@
if (biased_locker != NULL) {
_biased_locker_id = JFR_THREAD_ID(biased_locker);
}
- _safepoint_id = SafepointSynchronize::safepoint_counter();
+ _safepoint_id = SafepointSynchronize::safepoint_id();
clean_up_cached_monitor_info();
return;
} else {
@@ -589,7 +589,7 @@
virtual void doit() {
_status_code = bulk_revoke_or_rebias_at_safepoint((*_obj)(), _bulk_rebias, _attempt_rebias_of_object, _requesting_thread);
- _safepoint_id = SafepointSynchronize::safepoint_counter();
+ _safepoint_id = SafepointSynchronize::safepoint_id();
clean_up_cached_monitor_info();
}
--- a/src/hotspot/share/runtime/mutexLocker.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -82,7 +82,6 @@
Monitor* CGC_lock = NULL;
Monitor* STS_lock = NULL;
Monitor* FullGCCount_lock = NULL;
-Monitor* SATB_Q_CBL_mon = NULL;
Monitor* DirtyCardQ_CBL_mon = NULL;
Mutex* Shared_DirtyCardQ_lock = NULL;
Mutex* MarkStackFreeList_lock = NULL;
@@ -228,8 +227,6 @@
def(FullGCCount_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); // in support of ExplicitGCInvokesConcurrent
if (UseG1GC) {
- def(SATB_Q_CBL_mon , PaddedMonitor, access, true, Monitor::_safepoint_check_never);
-
def(DirtyCardQ_CBL_mon , PaddedMonitor, access, true, Monitor::_safepoint_check_never);
def(Shared_DirtyCardQ_lock , PaddedMutex , access + 1, true, Monitor::_safepoint_check_never);
@@ -246,8 +243,6 @@
def(MonitoringSupport_lock , PaddedMutex , native , true, Monitor::_safepoint_check_never); // used for serviceability monitoring support
}
if (UseShenandoahGC) {
- def(SATB_Q_CBL_mon , PaddedMonitor, access, true, Monitor::_safepoint_check_never);
-
def(StringDedupQueue_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never);
def(StringDedupTable_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never);
}
--- a/src/hotspot/share/runtime/mutexLocker.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/mutexLocker.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -77,8 +77,6 @@
// fore- & background GC threads.
extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet.
extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc
-extern Monitor* SATB_Q_CBL_mon; // Protects SATB Q
- // completed buffer queue.
extern Monitor* DirtyCardQ_CBL_mon; // Protects dirty card Q
// completed buffer queue.
extern Mutex* Shared_DirtyCardQ_lock; // Lock protecting dirty card
--- a/src/hotspot/share/runtime/safepoint.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/safepoint.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -118,12 +118,22 @@
}
}
+// SafepointCheck
+SafepointStateTracker::SafepointStateTracker(uint64_t safepoint_id, bool at_safepoint)
+ : _safepoint_id(safepoint_id), _at_safepoint(at_safepoint) {}
+
+bool SafepointStateTracker::safepoint_state_changed() {
+ return _safepoint_id != SafepointSynchronize::safepoint_id() ||
+ _at_safepoint != SafepointSynchronize::is_at_safepoint();
+}
+
// --------------------------------------------------------------------------------------------------
// Implementation of Safepoint begin/end
SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized;
int SafepointSynchronize::_waiting_to_block = 0;
volatile uint64_t SafepointSynchronize::_safepoint_counter = 0;
+uint64_t SafepointSynchronize::_safepoint_id = 0;
const uint64_t SafepointSynchronize::InactiveSafepointCounter = 0;
int SafepointSynchronize::_current_jni_active_count = 0;
@@ -154,7 +164,7 @@
--_waiting_to_block;
}
-static bool thread_not_running(ThreadSafepointState *cur_state) {
+bool SafepointSynchronize::thread_not_running(ThreadSafepointState *cur_state) {
if (!cur_state->is_running()) {
return true;
}
@@ -408,6 +418,9 @@
OrderAccess::fence();
+ // Set the new id
+ ++_safepoint_id;
+
#ifdef ASSERT
// Make sure all the threads were visited.
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *cur = jtiwh.next(); ) {
@@ -419,7 +432,7 @@
GCLocker::set_jni_lock_count(_current_jni_active_count);
post_safepoint_synchronize_event(sync_event,
- _safepoint_counter,
+ _safepoint_id,
initial_running,
_waiting_to_block, iterations);
@@ -429,14 +442,14 @@
// needs cleanup to be completed before running the GC op.
EventSafepointCleanup cleanup_event;
do_cleanup_tasks();
- post_safepoint_cleanup_event(cleanup_event, _safepoint_counter);
+ post_safepoint_cleanup_event(cleanup_event, _safepoint_id);
- post_safepoint_begin_event(begin_event, _safepoint_counter, nof_threads, _current_jni_active_count);
+ post_safepoint_begin_event(begin_event, _safepoint_id, nof_threads, _current_jni_active_count);
SafepointTracing::cleanup();
}
void SafepointSynchronize::disarm_safepoint() {
- uint64_t safepoint_id = _safepoint_counter;
+ uint64_t active_safepoint_counter = _safepoint_counter;
{
JavaThreadIteratorWithHandle jtiwh;
#ifdef ASSERT
@@ -475,7 +488,7 @@
jtiwh.rewind();
for (; JavaThread *current = jtiwh.next(); ) {
// Clear the visited flag to ensure that the critical counts are collected properly.
- DEBUG_ONLY(current->reset_visited_for_critical_count(safepoint_id);)
+ DEBUG_ONLY(current->reset_visited_for_critical_count(active_safepoint_counter);)
ThreadSafepointState* cur_state = current->safepoint_state();
assert(!cur_state->is_running(), "Thread not suspended at safepoint");
cur_state->restart(); // TSS _running
@@ -497,7 +510,6 @@
void SafepointSynchronize::end() {
assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
EventSafepointEnd event;
- uint64_t safepoint_id = _safepoint_counter;
assert(Thread::current()->is_VM_thread(), "Only VM thread can execute a safepoint");
disarm_safepoint();
@@ -506,7 +518,7 @@
SafepointTracing::end();
- post_safepoint_end_event(event, safepoint_id);
+ post_safepoint_end_event(event, safepoint_id());
}
bool SafepointSynchronize::is_cleanup_needed() {
@@ -554,7 +566,7 @@
_counters(counters) {}
void work(uint worker_id) {
- uint64_t safepoint_id = SafepointSynchronize::safepoint_counter();
+ uint64_t safepoint_id = SafepointSynchronize::safepoint_id();
// All threads deflate monitors and mark nmethods (if necessary).
Threads::possibly_parallel_threads_do(true, &_cleanup_threads_cl);
--- a/src/hotspot/share/runtime/safepoint.hpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/safepoint.hpp Fri Jun 28 14:36:42 2019 +0530
@@ -48,6 +48,14 @@
class ThreadSafepointState;
+class SafepointStateTracker {
+ uint64_t _safepoint_id;
+ bool _at_safepoint;
+public:
+ SafepointStateTracker(uint64_t safepoint_id, bool at_safepoint);
+ bool safepoint_state_changed();
+};
+
//
// Implements roll-forward to safepoint (safepoint synchronization)
//
@@ -77,6 +85,7 @@
friend class SafepointMechanism;
friend class ThreadSafepointState;
friend class HandshakeState;
+ friend class SafepointStateTracker;
// Threads might read this flag directly, without acquiring the Threads_lock:
static volatile SynchronizeState _state;
@@ -91,6 +100,11 @@
// safepoint.
static volatile uint64_t _safepoint_counter;
+ // A change in this counter or a change in the result of
+ // is_at_safepoint() are used by SafepointStateTracker::
+ // safepoint_state_changed() to determine its answer.
+ static uint64_t _safepoint_id;
+
// JavaThreads that need to block for the safepoint will stop on the
// _wait_barrier, where they can quickly be started again.
static WaitBarrier* _wait_barrier;
@@ -114,6 +128,7 @@
static void disarm_safepoint();
static void increment_jni_active_count();
static void decrement_waiting_to_block();
+ static bool thread_not_running(ThreadSafepointState *cur_state);
// Used in safepoint_safe to do a stable load of the thread state.
static bool try_stable_load_state(JavaThreadState *state,
@@ -127,6 +142,8 @@
// If true the VMThread may safely process the handshake operation for the JavaThread.
static bool handshake_safe(JavaThread *thread);
+ static uint64_t safepoint_counter() { return _safepoint_counter; }
+
public:
static void init(Thread* vmthread);
@@ -141,8 +158,15 @@
// Query
static bool is_at_safepoint() { return _state == _synchronized; }
static bool is_synchronizing() { return _state == _synchronizing; }
- static uint64_t safepoint_counter() { return _safepoint_counter; }
- static bool is_same_safepoint(uint64_t counter) { return (SafepointSynchronize::safepoint_counter() - counter) < 2; }
+
+ static uint64_t safepoint_id() {
+ return _safepoint_id;
+ }
+
+ static SafepointStateTracker safepoint_state_tracker() {
+ return SafepointStateTracker(safepoint_id(), is_at_safepoint());
+ }
+
// Exception handling for page polling
static void handle_polling_page_exception(JavaThread *thread);
--- a/src/hotspot/share/runtime/stubRoutines.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/stubRoutines.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "asm/codeBuffer.hpp"
+#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
--- a/src/hotspot/share/runtime/vmThread.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/runtime/vmThread.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -388,7 +388,7 @@
// 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 : JFR_THREAD_ID(op->calling_thread()));
- event->set_safepointId(evaluate_at_safepoint ? SafepointSynchronize::safepoint_counter() : 0);
+ event->set_safepointId(evaluate_at_safepoint ? SafepointSynchronize::safepoint_id() : 0);
event->commit();
}
--- a/src/hotspot/share/services/diagnosticCommand.cpp Wed Jun 26 14:28:47 2019 +0530
+++ b/src/hotspot/share/services/diagnosticCommand.cpp Fri Jun 28 14:36:42 2019 +0530
@@ -129,7 +129,7 @@
// Debug on cmd (only makes sense with JVMTI since the agentlib needs it).
#if INCLUDE_JVMTI
- DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DebugOnCmdStartDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<DebugOnCmdStartDCmd>(full_export, true, true));
#endif // INCLUDE_JVMTI
}
--- a/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDescImpl.java Fri Jun 28 14:36:42 2019 +0530
@@ -131,8 +131,14 @@
}
@Override
- public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) {
- return MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
+ public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
+ MethodType mtype = MethodType.fromMethodDescriptorString(descriptorString(), lookup.lookupClass().getClassLoader());
+ // let's check that the lookup has access to all the types in the method type
+ lookup.accessClass(mtype.returnType());
+ for (Class<?> paramType: mtype.parameterArray()) {
+ lookup.accessClass(paramType);
+ }
+ return mtype;
}
/**
--- a/src/java.base/share/classes/java/net/DatagramSocketImpl.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/java.base/share/classes/java/net/DatagramSocketImpl.java Fri Jun 28 14:36:42 2019 +0530
@@ -268,7 +268,7 @@
*
* @implSpec
* The default implementation of this method first checks that the given
- * socket option {code name} is not null, then throws {@code
+ * socket option {@code name} is not null, then throws {@code
* UnsupportedOperationException}. Subclasses should override this method
* with an appropriate implementation.
*
@@ -296,7 +296,7 @@
*
* @implSpec
* The default implementation of this method first checks that the given
- * socket option {code name} is not null, then throws {@code
+ * socket option {@code name} is not null, then throws {@code
* UnsupportedOperationException}. Subclasses should override this method
* with an appropriate implementation.
*
--- a/src/java.base/share/classes/java/net/URLStreamHandler.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/java.base/share/classes/java/net/URLStreamHandler.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,7 @@
*
* @implSpec
* The default implementation of this method first checks that the given
- * {code URL} and {code Proxy} are not null, then throws {@code
+ * {@code URL} and {@code Proxy} are not null, then throws {@code
* UnsupportedOperationException}. Subclasses should override this method
* with an appropriate implementation.
*
--- a/src/java.base/share/classes/java/util/DoubleSummaryStatistics.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/java.base/share/classes/java/util/DoubleSummaryStatistics.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,6 +59,8 @@
* implementation of {@link java.util.stream.Stream#collect Stream.collect()}
* provides the necessary partitioning, isolation, and merging of results for
* safe and efficient parallel execution.
+ *
+ * <p>This implementation does not check for overflow of the count.
* @since 1.8
*/
public class DoubleSummaryStatistics implements DoubleConsumer {
--- a/src/java.base/share/classes/java/util/IntSummaryStatistics.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/java.base/share/classes/java/util/IntSummaryStatistics.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
* provides the necessary partitioning, isolation, and merging of results for
* safe and efficient parallel execution.
*
- * <p>This implementation does not check for overflow of the sum.
+ * <p>This implementation does not check for overflow of the count or the sum.
* @since 1.8
*/
public class IntSummaryStatistics implements IntConsumer {
--- a/src/java.base/share/classes/java/util/LongSummaryStatistics.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/java.base/share/classes/java/util/LongSummaryStatistics.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,7 @@
* provides the necessary partitioning, isolation, and merging of results for
* safe and efficient parallel execution.
*
- * <p>This implementation does not check for overflow of the sum.
+ * <p>This implementation does not check for overflow of the count or the sum.
* @since 1.8
*/
public class LongSummaryStatistics implements LongConsumer, IntConsumer {
--- a/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java Fri Jun 28 14:36:42 2019 +0530
@@ -97,7 +97,7 @@
public String getDesktop() {
String gsi = AccessController.doPrivileged(
(PrivilegedAction<String>) ()
- -> System.getenv("GNOME_SESSION_ID"));
+ -> System.getenv("GNOME_DESKTOP_SESSION_ID"));
return (gsi != null) ? "gnome" : null;
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Fri Jun 28 14:36:42 2019 +0530
@@ -195,7 +195,8 @@
AOTDynamicTypeStore dynoStore = new AOTDynamicTypeStore();
AOTCompiledClass.setDynamicTypeStore(dynoStore);
- // AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, new HotSpotInvokeDynamicPlugin(dynoStore));
+ // AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, new
+ // HotSpotInvokeDynamicPlugin(dynoStore));
// Temporary workaround until JDK-8223533 is fixed.
// Disable invokedynamic support.
var indyPlugin = new HotSpotInvokeDynamicPlugin(dynoStore) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,6 +25,7 @@
package jdk.tools.jaotc;
+import java.util.HashMap;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
/**
@@ -56,17 +57,22 @@
INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED");
private final int value;
+ private static HashMap<Integer, MarkId> lookup = new HashMap<Integer, MarkId>();
+ static {
+ for (MarkId e : values()) {
+ lookup.put(e.value, e);
+ }
+ }
MarkId(String name) {
this.value = (int) (long) HotSpotJVMCIRuntime.runtime().getConfigStore().getConstants().get(name);
}
static MarkId getEnum(int value) {
- for (MarkId e : values()) {
- if (e.value == value) {
- return e;
- }
+ MarkId e = lookup.get(value);
+ if (e == null) {
+ throw new InternalError("Unknown enum value: " + value);
}
- throw new InternalError("Unknown enum value: " + value);
+ return e;
}
}
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,12 +28,12 @@
import static jdk.tools.jaotc.AOTCompiledClass.getType;
import static jdk.tools.jaotc.AOTCompiledClass.metadataName;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.HotSpotGraalServices;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
@@ -82,12 +82,6 @@
HotSpotGraalRuntimeProvider runtime = dataBuilder.getBackend().getRuntime();
ByteContainer methodMetadataContainer = binaryContainer.getMethodMetadataContainer();
- Method implicitExceptionsMethod = null;
- try {
- implicitExceptionsMethod = HotSpotMetaData.class.getDeclaredMethod("implicitExceptionBytes");
- } catch (NoSuchMethodException e) {
- }
-
// For each of the compiled java methods, create records holding information about them.
for (CompiledMethodInfo methodInfo : compiledClass.getCompiledMethods()) {
// Get the current offset in the methodmetadata container.
@@ -104,6 +98,7 @@
byte[] scopeDesc = metaData.scopesDescBytes();
byte[] relocationInfo = metaData.relocBytes();
byte[] oopMapInfo = metaData.oopMaps();
+ byte[] implicitExceptionBytes = HotSpotGraalServices.getImplicitExceptionBytes(metaData);
// create a global symbol at this position for this method
NativeOrderOutputStream metadataStream = new NativeOrderOutputStream();
@@ -148,10 +143,9 @@
NativeOrderOutputStream.PatchableInt scopeOffset = metadataStream.patchableInt();
NativeOrderOutputStream.PatchableInt relocationOffset = metadataStream.patchableInt();
NativeOrderOutputStream.PatchableInt exceptionOffset = metadataStream.patchableInt();
- NativeOrderOutputStream.PatchableInt implictTableOFfset = null;
-
- if (implicitExceptionsMethod != null) {
- implictTableOFfset = metadataStream.patchableInt();
+ NativeOrderOutputStream.PatchableInt implictTableOffset = null;
+ if (implicitExceptionBytes != null) {
+ implictTableOffset = metadataStream.patchableInt();
}
NativeOrderOutputStream.PatchableInt oopMapOffset = metadataStream.patchableInt();
metadataStream.align(8);
@@ -168,10 +162,9 @@
exceptionOffset.set(metadataStream.position());
metadataStream.put(metaData.exceptionBytes()).align(8);
- if (implicitExceptionsMethod != null) {
- implictTableOFfset.set(metadataStream.position());
- byte[] data = (byte[]) implicitExceptionsMethod.invoke(metaData);
- metadataStream.put(data).align(8);
+ if (implicitExceptionBytes != null) {
+ implictTableOffset.set(metadataStream.position());
+ metadataStream.put(implicitExceptionBytes).align(8);
}
// oopmaps should be last
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMap.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMap.java Fri Jun 28 14:36:42 2019 +0530
@@ -47,7 +47,7 @@
/**
* Memory efficient map data structure.
*
- * @since 1.0
+ * @since 19.0
*/
public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
@@ -57,14 +57,14 @@
*
* @return the previous value associated with {@code key}, or {@code null} if there was no
* mapping for {@code key}.
- * @since 1.0
+ * @since 19.0
*/
V put(K key, V value);
/**
* Copies all of the mappings from {@code other} to this map.
*
- * @since 1.0
+ * @since 19.0
*/
default void putAll(EconomicMap<K, V> other) {
MapCursor<K, V> e = other.getEntries();
@@ -76,7 +76,7 @@
/**
* Copies all of the mappings from {@code other} to this map.
*
- * @since 1.0
+ * @since 19.0
*/
default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
@@ -88,7 +88,7 @@
/**
* Removes all of the mappings from this map. The map will be empty after this call returns.
*
- * @since 1.0
+ * @since 19.0
*/
void clear();
@@ -98,14 +98,14 @@
*
* @return the previous value associated with {@code key}, or {@code null} if there was no
* mapping for {@code key}.
- * @since 1.0
+ * @since 19.0
*/
V removeKey(K key);
/**
* Returns a {@link MapCursor} view of the mappings contained in this map.
*
- * @since 1.0
+ * @since 19.0
*/
@Override
MapCursor<K, V> getEntries();
@@ -115,7 +115,7 @@
* all entries have been processed or the function throws an exception. Exceptions thrown by the
* function are relayed to the caller.
*
- * @since 1.0
+ * @since 19.0
*/
void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
@@ -123,7 +123,7 @@
* Creates a new map that guarantees insertion order on the key set with the default
* {@link Equivalence#DEFAULT} comparison strategy for keys.
*
- * @since 1.0
+ * @since 19.0
*/
static <K, V> EconomicMap<K, V> create() {
return EconomicMap.create(Equivalence.DEFAULT);
@@ -134,7 +134,7 @@
* {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
* capacity.
*
- * @since 1.0
+ * @since 19.0
*/
static <K, V> EconomicMap<K, V> create(int initialCapacity) {
return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
@@ -144,7 +144,7 @@
* Creates a new map that guarantees insertion order on the key set with the given comparison
* strategy for keys.
*
- * @since 1.0
+ * @since 19.0
*/
static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
return EconomicMapImpl.create(strategy, false);
@@ -155,7 +155,7 @@
* {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
* specified existing map.
*
- * @since 1.0
+ * @since 19.0
*/
static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
return EconomicMap.create(Equivalence.DEFAULT, m);
@@ -165,7 +165,7 @@
* Creates a new map that guarantees insertion order on the key set and copies all elements from
* the specified existing map.
*
- * @since 1.0
+ * @since 19.0
*/
static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
return EconomicMapImpl.create(strategy, m, false);
@@ -175,7 +175,7 @@
* Creates a new map that guarantees insertion order on the key set and initializes with a
* specified capacity.
*
- * @since 1.0
+ * @since 19.0
*/
static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
return EconomicMapImpl.create(strategy, initialCapacity, false);
@@ -184,7 +184,7 @@
/**
* Wraps an existing {@link Map} as an {@link EconomicMap}.
*
- * @since 1.0
+ * @since 19.0
*/
static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
return new EconomicMap<K, V>() {
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicSet.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicSet.java Fri Jun 28 14:36:42 2019 +0530
@@ -45,7 +45,7 @@
/**
* Memory efficient set data structure.
*
- * @since 1.0
+ * @since 19.0
*/
public interface EconomicSet<E> extends UnmodifiableEconomicSet<E> {
@@ -53,7 +53,7 @@
* Adds {@code element} to this set if it is not already present.
*
* @return {@code true} if this set did not already contain {@code element}.
- * @since 1.0
+ * @since 19.0
*/
boolean add(E element);
@@ -61,21 +61,21 @@
* Removes {@code element} from this set if it is present. This set will not contain
* {@code element} once the call returns.
*
- * @since 1.0
+ * @since 19.0
*/
void remove(E element);
/**
* Removes all of the elements from this set. The set will be empty after this call returns.
*
- * @since 1.0
+ * @since 19.0
*/
void clear();
/**
* Adds all of the elements in {@code other} to this set if they're not already present.
*
- * @since 1.0
+ * @since 19.0
*/
default void addAll(EconomicSet<E> other) {
addAll(other.iterator());
@@ -84,7 +84,7 @@
/**
* Adds all of the elements in {@code values} to this set if they're not already present.
*
- * @since 1.0
+ * @since 19.0
*/
default void addAll(Iterable<E> values) {
addAll(values.iterator());
@@ -94,7 +94,7 @@
* Adds all of the elements enumerated by {@code iterator} to this set if they're not already
* present.
*
- * @since 1.0
+ * @since 19.0
*/
default void addAll(Iterator<E> iterator) {
while (iterator.hasNext()) {
@@ -105,7 +105,7 @@
/**
* Removes from this set all of its elements that are contained in {@code other}.
*
- * @since 1.0
+ * @since 19.0
*/
default void removeAll(EconomicSet<E> other) {
removeAll(other.iterator());
@@ -114,7 +114,7 @@
/**
* Removes from this set all of its elements that are contained in {@code values}.
*
- * @since 1.0
+ * @since 19.0
*/
default void removeAll(Iterable<E> values) {
removeAll(values.iterator());
@@ -123,7 +123,7 @@
/**
* Removes from this set all of its elements that are enumerated by {@code iterator}.
*
- * @since 1.0
+ * @since 19.0
*/
default void removeAll(Iterator<E> iterator) {
while (iterator.hasNext()) {
@@ -134,7 +134,7 @@
/**
* Removes from this set all of its elements that are not contained in {@code other}.
*
- * @since 1.0
+ * @since 19.0
*/
default void retainAll(EconomicSet<E> other) {
Iterator<E> iterator = iterator();
@@ -150,7 +150,7 @@
* Creates a new set guaranteeing insertion order when iterating over its elements with the
* default {@link Equivalence#DEFAULT} comparison strategy.
*
- * @since 1.0
+ * @since 19.0
*/
static <E> EconomicSet<E> create() {
return EconomicSet.create(Equivalence.DEFAULT);
@@ -159,7 +159,7 @@
/**
* Creates a new set guaranteeing insertion order when iterating over its elements.
*
- * @since 1.0
+ * @since 19.0
*/
static <E> EconomicSet<E> create(Equivalence strategy) {
return EconomicMapImpl.create(strategy, true);
@@ -170,7 +170,7 @@
* default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
* specified collection.
*
- * @since 1.0
+ * @since 19.0
*/
static <E> EconomicSet<E> create(int initialCapacity) {
return EconomicSet.create(Equivalence.DEFAULT, initialCapacity);
@@ -181,7 +181,7 @@
* default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
* specified collection.
*
- * @since 1.0
+ * @since 19.0
*/
static <E> EconomicSet<E> create(UnmodifiableEconomicSet<E> c) {
return EconomicSet.create(Equivalence.DEFAULT, c);
@@ -191,7 +191,7 @@
* Creates a new set guaranteeing insertion order when iterating over its elements and
* initializes with the given capacity.
*
- * @since 1.0
+ * @since 19.0
*/
static <E> EconomicSet<E> create(Equivalence strategy, int initialCapacity) {
return EconomicMapImpl.create(strategy, initialCapacity, true);
@@ -201,7 +201,7 @@
* Creates a new set guaranteeing insertion order when iterating over its elements and inserts
* all elements of the specified collection.
*
- * @since 1.0
+ * @since 19.0
*/
static <E> EconomicSet<E> create(Equivalence strategy, UnmodifiableEconomicSet<E> c) {
return EconomicMapImpl.create(strategy, c, true);
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Equivalence.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Equivalence.java Fri Jun 28 14:36:42 2019 +0530
@@ -44,7 +44,7 @@
* Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT},
* {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}.
*
- * @since 1.0
+ * @since 19.0
*/
public abstract class Equivalence {
@@ -53,7 +53,7 @@
* for obtaining hash values. Do not change the logic of this class as it may be inlined in
* other places.
*
- * @since 1.0
+ * @since 19.0
*/
public static final Equivalence DEFAULT = new Equivalence() {
@@ -72,7 +72,7 @@
* Identity equivalence using {@code ==} to check equality and {@link #hashCode()} for obtaining
* hash values. Do not change the logic of this class as it may be inlined in other places.
*
- * @since 1.0
+ * @since 19.0
*/
public static final Equivalence IDENTITY = new Equivalence() {
@@ -92,7 +92,7 @@
* {@link System#identityHashCode(Object)} for obtaining hash values. Do not change the logic of
* this class as it may be inlined in other places.
*
- * @since 1.0
+ * @since 19.0
*/
public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() {
@@ -110,7 +110,7 @@
/**
* Subclass for creating custom equivalence definitions.
*
- * @since 1.0
+ * @since 19.0
*/
protected Equivalence() {
}
@@ -119,14 +119,14 @@
* Returns {@code true} if the non-{@code null} arguments are equal to each other and
* {@code false} otherwise.
*
- * @since 1.0
+ * @since 19.0
*/
public abstract boolean equals(Object a, Object b);
/**
* Returns the hash code of a non-{@code null} argument {@code o}.
*
- * @since 1.0
+ * @since 19.0
*/
public abstract int hashCode(Object o);
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/MapCursor.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/MapCursor.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,7 @@
/**
* Cursor to iterate over a mutable map.
*
- * @since 1.0
+ * @since 19.0
*/
public interface MapCursor<K, V> extends UnmodifiableMapCursor<K, V> {
/**
@@ -51,7 +51,7 @@
* {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on
* the current entry.
*
- * @since 1.0
+ * @since 19.0
*/
void remove();
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Pair.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Pair.java Fri Jun 28 14:36:42 2019 +0530
@@ -45,7 +45,7 @@
/**
* Utility class representing a pair of values.
*
- * @since 1.0
+ * @since 19.0
*/
public final class Pair<L, R> {
@@ -57,7 +57,7 @@
/**
* Returns an empty pair.
*
- * @since 1.0
+ * @since 19.0
*/
@SuppressWarnings("unchecked")
public static <L, R> Pair<L, R> empty() {
@@ -69,7 +69,7 @@
* {@code left} is null.
*
* @return the constructed pair or an empty pair if {@code left} is null.
- * @since 1.0
+ * @since 19.0
*/
public static <L, R> Pair<L, R> createLeft(L left) {
if (left == null) {
@@ -84,7 +84,7 @@
* {@code right} is null.
*
* @return the constructed pair or an empty pair if {@code right} is null.
- * @since 1.0
+ * @since 19.0
*/
public static <L, R> Pair<L, R> createRight(R right) {
if (right == null) {
@@ -99,7 +99,7 @@
* {@code right}, or returns an empty pair if both inputs are null.
*
* @return the constructed pair or an empty pair if both inputs are null.
- * @since 1.0
+ * @since 19.0
*/
public static <L, R> Pair<L, R> create(L left, R right) {
if (right == null && left == null) {
@@ -117,7 +117,7 @@
/**
* Returns the left value of this pair.
*
- * @since 1.0
+ * @since 19.0
*/
public L getLeft() {
return left;
@@ -126,7 +126,7 @@
/**
* Returns the right value of this pair.
*
- * @since 1.0
+ * @since 19.0
*/
public R getRight() {
return right;
@@ -135,7 +135,7 @@
/**
* {@inheritDoc}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
public int hashCode() {
@@ -145,7 +145,7 @@
/**
* {@inheritDoc}
*
- * @since 1.0
+ * @since 19.0
*/
@SuppressWarnings("unchecked")
@Override
@@ -165,7 +165,7 @@
/**
* {@inheritDoc}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
public String toString() {
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicMap.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicMap.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,7 @@
/**
* Unmodifiable memory efficient map data structure.
*
- * @since 1.0
+ * @since 19.0
*/
public interface UnmodifiableEconomicMap<K, V> {
@@ -51,7 +51,7 @@
* Returns the value to which {@code key} is mapped, or {@code null} if this map contains no
* mapping for {@code key}.
*
- * @since 1.0
+ * @since 19.0
*/
V get(K key);
@@ -59,7 +59,7 @@
* Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map
* contains no mapping for {@code key}.
*
- * @since 1.0
+ * @since 19.0
*/
default V get(K key, V defaultValue) {
V v = get(key);
@@ -72,42 +72,42 @@
/**
* Returns {@code true} if this map contains a mapping for {@code key}.
*
- * @since 1.0
+ * @since 19.0
*/
boolean containsKey(K key);
/**
* Returns the number of key-value mappings in this map.
*
- * @since 1.0
+ * @since 19.0
*/
int size();
/**
* Returns {@code true} if this map contains no key-value mappings.
*
- * @since 1.0
+ * @since 19.0
*/
boolean isEmpty();
/**
* Returns a {@link Iterable} view of the values contained in this map.
*
- * @since 1.0
+ * @since 19.0
*/
Iterable<V> getValues();
/**
* Returns a {@link Iterable} view of the keys contained in this map.
*
- * @since 1.0
+ * @since 19.0
*/
Iterable<K> getKeys();
/**
* Returns a {@link UnmodifiableMapCursor} view of the mappings contained in this map.
*
- * @since 1.0
+ * @since 19.0
*/
UnmodifiableMapCursor<K, V> getEntries();
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicSet.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicSet.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,28 +43,28 @@
/**
* Unmodifiable memory efficient set data structure.
*
- * @since 1.0
+ * @since 19.0
*/
public interface UnmodifiableEconomicSet<E> extends Iterable<E> {
/**
* Returns {@code true} if this set contains a mapping for the {@code element}.
*
- * @since 1.0
+ * @since 19.0
*/
boolean contains(E element);
/**
* Returns the number of elements in this set.
*
- * @since 1.0
+ * @since 19.0
*/
int size();
/**
* Returns {@code true} if this set contains no elements.
*
- * @since 1.0
+ * @since 19.0
*/
boolean isEmpty();
@@ -76,7 +76,7 @@
* @return an array containing all the elements in this set.
* @throws UnsupportedOperationException if the length of {@code target} does not equal the size
* of this set.
- * @since 1.0
+ * @since 19.0
*/
default E[] toArray(E[] target) {
if (target.length != size()) {
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableMapCursor.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableMapCursor.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,28 +43,28 @@
/**
* Cursor to iterate over a map without changing its contents.
*
- * @since 1.0
+ * @since 19.0
*/
public interface UnmodifiableMapCursor<K, V> {
/**
* Advances to the next entry.
*
* @return {@code true} if a next entry exists, {@code false} if there is no next entry.
- * @since 1.0
+ * @since 19.0
*/
boolean advance();
/**
* The key of the current entry.
*
- * @since 1.0
+ * @since 19.0
*/
K getKey();
/**
* The value of the current entry.
*
- * @since 1.0
+ * @since 19.0
*/
V getValue();
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,7 +31,7 @@
* @see jdk.internal.vm.compiler.collections.EconomicMap
* @see jdk.internal.vm.compiler.collections.EconomicSet
*
- * @since 1.0
+ * @since 19.0
*/
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraal.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraal.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,67 +33,43 @@
public class LibGraal {
public static boolean isAvailable() {
- return isCurrentRuntime() || libgraalIsolate != 0L;
+ return inLibGraal() || isolate != 0L;
}
- public static boolean isCurrentRuntime() {
+ public static boolean inLibGraal() {
return Services.IS_IN_NATIVE_IMAGE;
}
- public static long getIsolate() {
- if (isCurrentRuntime() || !isAvailable()) {
- throw new IllegalStateException();
- }
- return libgraalIsolate;
- }
-
- public static long getIsolateThread() {
- if (isCurrentRuntime()) {
- throw new IllegalStateException();
- }
- return CURRENT_ISOLATE_THREAD.get();
- }
-
- @SuppressWarnings("unused")
- public static long[] registerNativeMethods(HotSpotJVMCIRuntime runtime, Class<?> clazz) {
+ public static void registerNativeMethods(HotSpotJVMCIRuntime runtime, Class<?> clazz) {
if (clazz.isPrimitive()) {
throw new IllegalArgumentException();
}
- if (isCurrentRuntime() || !isAvailable()) {
+ if (inLibGraal() || !isAvailable()) {
throw new IllegalStateException();
}
- // Waiting for https://bugs.openjdk.java.net/browse/JDK-8220623
- // return runtime.registerNativeMethods(clazz);
- throw new IllegalStateException("Requires JDK-8220623");
+ runtime.registerNativeMethods(clazz);
}
- @SuppressWarnings("unused")
public static long translate(HotSpotJVMCIRuntime runtime, Object obj) {
if (!isAvailable()) {
throw new IllegalStateException();
}
- // return runtime.translate(obj);
- throw new IllegalStateException("Requires JDK-8220623");
+ if (!inLibGraal() && LibGraalScope.currentScope.get() == null) {
+ throw new IllegalStateException("Not within a " + LibGraalScope.class.getName());
+ }
+ return runtime.translate(obj);
}
- @SuppressWarnings("unused")
public static <T> T unhand(HotSpotJVMCIRuntime runtime, Class<T> type, long handle) {
if (!isAvailable()) {
throw new IllegalStateException();
}
- // return runtime.unhand(type, handle);
- throw new IllegalStateException("Requires JDK-8220623");
+ if (!inLibGraal() && LibGraalScope.currentScope.get() == null) {
+ throw new IllegalStateException("Not within a " + LibGraalScope.class.getName());
+ }
+ return runtime.unhand(type, handle);
}
- private static final ThreadLocal<Long> CURRENT_ISOLATE_THREAD = new ThreadLocal<>() {
- @Override
- protected Long initialValue() {
- return attachThread(libgraalIsolate);
- }
- };
-
- private static final long libgraalIsolate = Services.IS_BUILDING_NATIVE_IMAGE ? 0L : initializeLibgraal();
-
private static long initializeLibgraal() {
try {
// Initialize JVMCI to ensure JVMCI opens its packages to
@@ -101,20 +77,27 @@
// below will fail on JDK13+.
Services.initializeJVMCI();
- // Waiting for https://bugs.openjdk.java.net/browse/JDK-8220623
- // HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
- // long[] nativeInterface = runtime.registerNativeMethods(LibGraal.class);
- // return nativeInterface[1];
- return 0L;
+ HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
+ long[] nativeInterface = runtime.registerNativeMethods(LibGraal.class);
+ return nativeInterface[1];
} catch (UnsupportedOperationException e) {
return 0L;
}
}
- /**
- * Attaches the current thread to a thread in {@code isolate}.
- *
- * @param isolate
- */
- private static native long attachThread(long isolate);
+ static final long isolate = Services.IS_BUILDING_NATIVE_IMAGE ? 0L : initializeLibgraal();
+
+ static boolean isCurrentThreadAttached(HotSpotJVMCIRuntime runtime) {
+ return runtime.isCurrentThreadAttached();
+ }
+
+ static boolean attachCurrentThread(HotSpotJVMCIRuntime runtime) {
+ return runtime.attachCurrentThread(false);
+ }
+
+ static void detachCurrentThread(HotSpotJVMCIRuntime runtime) {
+ runtime.detachCurrentThread();
+ }
+
+ static native long getCurrentIsolateThread(long iso);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/LibGraalScope.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package jdk.internal.vm.compiler.libgraal;
+
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+
+/**
+ * Scope for calling CEntryPoints in libgraal. {@linkplain #LibGraalScope(HotSpotJVMCIRuntime)
+ * Opening} a scope attaches the current thread to libgraal and {@linkplain #close() closing} it
+ * detaches the current thread.
+ */
+public final class LibGraalScope implements AutoCloseable {
+
+ static final ThreadLocal<LibGraalScope> currentScope = new ThreadLocal<>();
+
+ private final LibGraalScope parent;
+ private final boolean topLevel;
+ private final HotSpotJVMCIRuntime runtime;
+ private final long isolateThread;
+
+ /**
+ * Gets the isolate thread associated with the current thread. The current thread must be in an
+ * {@linkplain #LibGraalScope(HotSpotJVMCIRuntime) opened} scope.
+ *
+ * @returns a value that can be used for the IsolateThreadContext argument of a {@code native}
+ * method {@link LibGraal#registerNativeMethods linked} to a CEntryPoint function in
+ * libgraal
+ * @throws IllegalStateException if not the current thread is not attached to libgraal
+ */
+ public static long getIsolateThread() {
+ LibGraalScope scope = currentScope.get();
+ if (scope == null) {
+ throw new IllegalStateException("Cannot get isolate thread outside of a " + LibGraalScope.class.getSimpleName());
+ }
+ return scope.isolateThread;
+ }
+
+ /**
+ * Enters a scope for making calls into libgraal. If there is no existing libgraal scope for the
+ * current thread, the current thread is attached to libgraal. When the outer most scope is
+ * closed, the current thread is detached from libgraal.
+ *
+ * This must be used in a try-with-resources statement.
+ *
+ * This cannot be called from {@linkplain LibGraal#inLibGraal() within} libgraal.
+ *
+ * @throws IllegalStateException if libgraal is {@linkplain LibGraal#isAvailable() unavailable}
+ * or {@link LibGraal#inLibGraal()} returns true
+ */
+ public LibGraalScope(HotSpotJVMCIRuntime runtime) {
+ if (LibGraal.inLibGraal() || !LibGraal.isAvailable()) {
+ throw new IllegalStateException();
+ }
+ this.runtime = runtime;
+ parent = currentScope.get();
+ boolean top = false;
+ if (parent == null) {
+ top = LibGraal.attachCurrentThread(runtime);
+ isolateThread = LibGraal.getCurrentIsolateThread(LibGraal.isolate);
+ } else {
+ isolateThread = parent.isolateThread;
+ }
+ topLevel = top;
+ currentScope.set(this);
+ }
+
+ @Override
+ public void close() {
+ if (topLevel) {
+ LibGraal.detachCurrentThread(runtime);
+ }
+ currentScope.set(parent);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java Fri Jun 28 14:36:42 2019 +0530
@@ -162,6 +162,9 @@
}
res.put(key, value);
}
+ if (in.available() != 0) {
+ throw new IllegalArgumentException(in.available() + " undecoded bytes");
+ }
} catch (IOException ioe) {
throw new IllegalArgumentException(ioe);
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/ComparableWord.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/ComparableWord.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,7 @@
/**
* A machine-word-sized value that can be compared for equality.
*
- * @since 1.0
+ * @since 19.0
*/
public interface ComparableWord extends WordBase {
@@ -53,7 +53,7 @@
* @param val value to which this word is to be compared.
* @return {@code this == val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean equal(ComparableWord val);
@@ -63,7 +63,7 @@
* @param val value to which this word is to be compared.
* @return {@code this != val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean notEqual(ComparableWord val);
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/LocationIdentity.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/LocationIdentity.java Fri Jun 28 14:36:42 2019 +0530
@@ -50,7 +50,7 @@
* comparing two {@link LocationIdentity} values for equality. Likewise, they must not use
* {@link java.util.IdentityHashMap}s with {@link LocationIdentity} values as keys.
*
- * @since 1.0
+ * @since 19.0
*/
public abstract class LocationIdentity {
@@ -82,7 +82,7 @@
* Creates a new location identity. Subclasses are responsible to provide proper implementations
* of {@link #equals} and {@link #hashCode}.
*
- * @since 1.0
+ * @since 19.0
*/
protected LocationIdentity() {
}
@@ -92,7 +92,7 @@
* such a location kill all reads from mutable locations and a read from this location is killed
* by any write (except for initialization writes).
*
- * @since 1.0
+ * @since 19.0
*/
public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity();
@@ -101,7 +101,7 @@
* is written. Kills no read. The previous value at the given location must be either
* uninitialized or null. Writes to this location do not need a GC pre-barrier.
*
- * @since 1.0
+ * @since 19.0
*/
public static final LocationIdentity INIT_LOCATION = new InitLocationIdentity();
@@ -110,7 +110,7 @@
* such a location kill all reads from mutable locations and a read from this location is killed
* by any write (except for initialization writes).
*
- * @since 1.0
+ * @since 19.0
*/
public static LocationIdentity any() {
return ANY_LOCATION;
@@ -121,7 +121,7 @@
* is written. Kills no read. The previous value at the given location must be either
* uninitialized or null. Writes to this location do not need a GC pre-barrier.
*
- * @since 1.0
+ * @since 19.0
*/
public static LocationIdentity init() {
return INIT_LOCATION;
@@ -131,14 +131,14 @@
* Denotes a location is unchanging in all cases. Not that this is different than the Java
* notion of final which only requires definite assignment.
*
- * @since 1.0
+ * @since 19.0
*/
public abstract boolean isImmutable();
/**
* The inversion of {@link #isImmutable}.
*
- * @since 1.0
+ * @since 19.0
*/
public final boolean isMutable() {
return !isImmutable();
@@ -147,7 +147,7 @@
/**
* Returns true if this location identity is {@link #any}.
*
- * @since 1.0
+ * @since 19.0
*/
public final boolean isAny() {
return this == ANY_LOCATION;
@@ -156,7 +156,7 @@
/**
* Returns true if this location identity is {@link #init}.
*
- * @since 1.0
+ * @since 19.0
*/
public final boolean isInit() {
return this == INIT_LOCATION;
@@ -165,7 +165,7 @@
/**
* Returns true if this location identity is not {@link #any}.
*
- * @since 1.0
+ * @since 19.0
*/
public final boolean isSingle() {
return this != ANY_LOCATION;
@@ -175,7 +175,7 @@
* Returns true if the memory slice denoted by this location identity may overlap with the
* provided other location identity.
*
- * @since 1.0
+ * @since 19.0
*/
public final boolean overlaps(LocationIdentity other) {
return isAny() || other.isAny() || this.equals(other);
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/Pointer.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/Pointer.java Fri Jun 28 14:36:42 2019 +0530
@@ -47,7 +47,7 @@
* null checks, read- or write barriers. Even when the VM uses compressed pointers, then readObject
* and writeObject methods access uncompressed pointers.
*
- * @since 1.0
+ * @since 19.0
*/
public interface Pointer extends UnsignedWord, PointerBase {
@@ -58,7 +58,7 @@
*
* @return this Pointer cast to Object.
*
- * @since 1.0
+ * @since 19.0
*/
Object toObject();
@@ -69,7 +69,7 @@
*
* @return this Pointer cast to non-null Object.
*
- * @since 1.0
+ * @since 19.0
*/
Object toObjectNonNull();
@@ -85,7 +85,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
byte readByte(WordBase offset, LocationIdentity locationIdentity);
@@ -101,7 +101,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
char readChar(WordBase offset, LocationIdentity locationIdentity);
@@ -117,7 +117,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
short readShort(WordBase offset, LocationIdentity locationIdentity);
@@ -133,7 +133,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
int readInt(WordBase offset, LocationIdentity locationIdentity);
@@ -149,7 +149,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
long readLong(WordBase offset, LocationIdentity locationIdentity);
@@ -165,7 +165,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
float readFloat(WordBase offset, LocationIdentity locationIdentity);
@@ -181,7 +181,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
double readDouble(WordBase offset, LocationIdentity locationIdentity);
@@ -197,7 +197,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
<T extends WordBase> T readWord(WordBase offset, LocationIdentity locationIdentity);
@@ -213,7 +213,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
Object readObject(WordBase offset, LocationIdentity locationIdentity);
@@ -225,7 +225,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
byte readByte(int offset, LocationIdentity locationIdentity);
@@ -237,7 +237,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
char readChar(int offset, LocationIdentity locationIdentity);
@@ -249,7 +249,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
short readShort(int offset, LocationIdentity locationIdentity);
@@ -261,7 +261,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
int readInt(int offset, LocationIdentity locationIdentity);
@@ -273,7 +273,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
long readLong(int offset, LocationIdentity locationIdentity);
@@ -285,7 +285,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
float readFloat(int offset, LocationIdentity locationIdentity);
@@ -297,7 +297,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
double readDouble(int offset, LocationIdentity locationIdentity);
@@ -309,7 +309,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
<T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity);
@@ -321,7 +321,7 @@
* @param locationIdentity the identity of the read
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
Object readObject(int offset, LocationIdentity locationIdentity);
@@ -337,7 +337,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity);
@@ -353,7 +353,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeChar(WordBase offset, char val, LocationIdentity locationIdentity);
@@ -369,7 +369,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeShort(WordBase offset, short val, LocationIdentity locationIdentity);
@@ -385,7 +385,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeInt(WordBase offset, int val, LocationIdentity locationIdentity);
@@ -401,7 +401,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeLong(WordBase offset, long val, LocationIdentity locationIdentity);
@@ -417,7 +417,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity);
@@ -433,7 +433,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity);
@@ -449,7 +449,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
@@ -465,7 +465,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity);
@@ -481,7 +481,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
@@ -493,7 +493,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeByte(int offset, byte val, LocationIdentity locationIdentity);
@@ -505,7 +505,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeChar(int offset, char val, LocationIdentity locationIdentity);
@@ -517,7 +517,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeShort(int offset, short val, LocationIdentity locationIdentity);
@@ -529,7 +529,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeInt(int offset, int val, LocationIdentity locationIdentity);
@@ -541,7 +541,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeLong(int offset, long val, LocationIdentity locationIdentity);
@@ -553,7 +553,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeFloat(int offset, float val, LocationIdentity locationIdentity);
@@ -565,7 +565,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeDouble(int offset, double val, LocationIdentity locationIdentity);
@@ -577,7 +577,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
@@ -589,7 +589,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void initializeLong(int offset, long val, LocationIdentity locationIdentity);
@@ -601,7 +601,7 @@
* @param locationIdentity the identity of the write
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeObject(int offset, Object val, LocationIdentity locationIdentity);
@@ -616,7 +616,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
byte readByte(WordBase offset);
@@ -631,7 +631,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
char readChar(WordBase offset);
@@ -646,7 +646,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
short readShort(WordBase offset);
@@ -661,7 +661,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
int readInt(WordBase offset);
@@ -676,7 +676,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
long readLong(WordBase offset);
@@ -691,7 +691,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
float readFloat(WordBase offset);
@@ -706,7 +706,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
double readDouble(WordBase offset);
@@ -721,7 +721,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
<T extends WordBase> T readWord(WordBase offset);
@@ -736,7 +736,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
Object readObject(WordBase offset);
@@ -747,7 +747,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
byte readByte(int offset);
@@ -758,7 +758,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
char readChar(int offset);
@@ -769,7 +769,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
short readShort(int offset);
@@ -780,7 +780,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
int readInt(int offset);
@@ -791,7 +791,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
long readLong(int offset);
@@ -802,7 +802,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
float readFloat(int offset);
@@ -813,7 +813,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
double readDouble(int offset);
@@ -824,7 +824,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
<T extends WordBase> T readWord(int offset);
@@ -835,7 +835,7 @@
* @param offset the signed offset for the memory access
* @return the result of the memory access
*
- * @since 1.0
+ * @since 19.0
*/
Object readObject(int offset);
@@ -850,7 +850,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeByte(WordBase offset, byte val);
@@ -865,7 +865,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeChar(WordBase offset, char val);
@@ -880,7 +880,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeShort(WordBase offset, short val);
@@ -895,7 +895,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeInt(WordBase offset, int val);
@@ -910,7 +910,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeLong(WordBase offset, long val);
@@ -925,7 +925,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeFloat(WordBase offset, float val);
@@ -940,7 +940,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeDouble(WordBase offset, double val);
@@ -955,7 +955,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeWord(WordBase offset, WordBase val);
@@ -970,7 +970,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeObject(WordBase offset, Object val);
@@ -990,7 +990,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
int compareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
@@ -1010,7 +1010,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
@@ -1030,7 +1030,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
<T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
@@ -1050,7 +1050,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
@@ -1070,7 +1070,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
@@ -1090,7 +1090,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
@@ -1110,7 +1110,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapWord(WordBase offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
@@ -1130,7 +1130,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
@@ -1141,7 +1141,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeByte(int offset, byte val);
@@ -1152,7 +1152,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeChar(int offset, char val);
@@ -1163,7 +1163,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeShort(int offset, short val);
@@ -1174,7 +1174,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeInt(int offset, int val);
@@ -1185,7 +1185,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeLong(int offset, long val);
@@ -1196,7 +1196,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeFloat(int offset, float val);
@@ -1207,7 +1207,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeDouble(int offset, double val);
@@ -1218,7 +1218,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeWord(int offset, WordBase val);
@@ -1229,7 +1229,7 @@
* @param offset the signed offset for the memory access
* @param val the value to be written to memory
*
- * @since 1.0
+ * @since 19.0
*/
void writeObject(int offset, Object val);
@@ -1245,7 +1245,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
@@ -1261,7 +1261,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
@@ -1277,7 +1277,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
<T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
@@ -1293,7 +1293,7 @@
* @return The value that was read for comparison, which is {@code expectedValue} if the
* exchange was performed.
*
- * @since 1.0
+ * @since 19.0
*/
Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
@@ -1309,7 +1309,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
@@ -1325,7 +1325,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
@@ -1341,7 +1341,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
@@ -1357,7 +1357,7 @@
* @return {@code true} if successful. False return indicates that the actual value was not
* equal to the expected value.
*
- * @since 1.0
+ * @since 19.0
*/
boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
@@ -1371,7 +1371,7 @@
* @param val value to be added to this Pointer.
* @return {@code this + val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer add(UnsignedWord val);
@@ -1382,7 +1382,7 @@
* @param val value to be added to this Pointer.
* @return {@code this + val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer add(int val);
@@ -1393,7 +1393,7 @@
* @param val value to be subtracted from this Pointer.
* @return {@code this - val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer subtract(UnsignedWord val);
@@ -1404,7 +1404,7 @@
* @param val value to be subtracted from this Pointer.
* @return {@code this - val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer subtract(int val);
@@ -1415,7 +1415,7 @@
* @param val value to be AND'ed with this Pointer.
* @return {@code this & val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer and(UnsignedWord val);
@@ -1426,7 +1426,7 @@
* @param val value to be AND'ed with this Pointer.
* @return {@code this & val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer and(int val);
@@ -1437,7 +1437,7 @@
* @param val value to be OR'ed with this Pointer.
* @return {@code this | val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer or(UnsignedWord val);
@@ -1448,7 +1448,7 @@
* @param val value to be OR'ed with this Pointer.
* @return {@code this | val}
*
- * @since 1.0
+ * @since 19.0
*/
@Override
Pointer or(int val);
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/PointerBase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/PointerBase.java Fri Jun 28 14:36:42 2019 +0530
@@ -44,21 +44,21 @@
* Marker interface for all {@link WordBase word types} that have the semantic of a pointer (but not
* necessarily all the memory access methods defined in {@link Pointer}).
*
- * @since 1.0
+ * @since 19.0
*/
public interface PointerBase extends ComparableWord {
/**
* Returns true if this pointer is the {@link WordFactory#nullPointer null pointer}.
*
- * @since 1.0
+ * @since 19.0
*/
boolean isNull();
/**
* Returns true if this pointer is not the {@link WordFactory#nullPointer null pointer}.
*
- * @since 1.0
+ * @since 19.0
*/
boolean isNonNull();
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/SignedWord.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/SignedWord.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,7 @@
/**
* Represents a signed word-sized value.
*
- * @since 1.0
+ * @since 19.0
*/
public interface SignedWord extends ComparableWord {
@@ -53,7 +53,7 @@
* @param val value to be added to this Signed.
* @return {@code this + val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord add(SignedWord val);
@@ -63,7 +63,7 @@
* @param val value to be subtracted from this Signed.
* @return {@code this - val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord subtract(SignedWord val);
@@ -73,7 +73,7 @@
* @param val value to be multiplied by this Signed.
* @return {@code this * val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord multiply(SignedWord val);
@@ -83,7 +83,7 @@
* @param val value by which this Signed is to be divided.
* @return {@code this / val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord signedDivide(SignedWord val);
@@ -93,7 +93,7 @@
* @param val value by which this Signed is to be divided, and the remainder computed.
* @return {@code this % val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord signedRemainder(SignedWord val);
@@ -103,7 +103,7 @@
* @param n shift distance, in bits.
* @return {@code this << n}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord shiftLeft(UnsignedWord n);
@@ -113,7 +113,7 @@
* @param n shift distance, in bits.
* @return {@code this >> n}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord signedShiftRight(UnsignedWord n);
@@ -124,7 +124,7 @@
* @param val value to be AND'ed with this Signed.
* @return {@code this & val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord and(SignedWord val);
@@ -135,7 +135,7 @@
* @param val value to be OR'ed with this Signed.
* @return {@code this | val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord or(SignedWord val);
@@ -146,7 +146,7 @@
* @param val value to be XOR'ed with this Signed.
* @return {@code this ^ val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord xor(SignedWord val);
@@ -156,7 +156,7 @@
*
* @return {@code ~this}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord not();
@@ -166,7 +166,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this == val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean equal(SignedWord val);
@@ -176,7 +176,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this != val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean notEqual(SignedWord val);
@@ -186,7 +186,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this < val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean lessThan(SignedWord val);
@@ -196,7 +196,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this <= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean lessOrEqual(SignedWord val);
@@ -206,7 +206,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this > val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean greaterThan(SignedWord val);
@@ -216,7 +216,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this >= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean greaterOrEqual(SignedWord val);
@@ -226,7 +226,7 @@
* @param val value to be added to this Signed.
* @return {@code this + val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord add(int val);
@@ -236,7 +236,7 @@
* @param val value to be subtracted from this Signed.
* @return {@code this - val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord subtract(int val);
@@ -246,7 +246,7 @@
* @param val value to be multiplied by this Signed.
* @return {@code this * val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord multiply(int val);
@@ -256,7 +256,7 @@
* @param val value by which this Signed is to be divided.
* @return {@code this / val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord signedDivide(int val);
@@ -266,7 +266,7 @@
* @param val value by which this Signed is to be divided, and the remainder computed.
* @return {@code this % val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord signedRemainder(int val);
@@ -276,7 +276,7 @@
* @param n shift distance, in bits.
* @return {@code this << n}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord shiftLeft(int n);
@@ -286,7 +286,7 @@
* @param n shift distance, in bits.
* @return {@code this >> n}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord signedShiftRight(int n);
@@ -297,7 +297,7 @@
* @param val value to be AND'ed with this Signed.
* @return {@code this & val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord and(int val);
@@ -308,7 +308,7 @@
* @param val value to be OR'ed with this Signed.
* @return {@code this | val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord or(int val);
@@ -319,7 +319,7 @@
* @param val value to be XOR'ed with this Signed.
* @return {@code this ^ val}
*
- * @since 1.0
+ * @since 19.0
*/
SignedWord xor(int val);
@@ -329,7 +329,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this == val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean equal(int val);
@@ -339,7 +339,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this != val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean notEqual(int val);
@@ -349,7 +349,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this < val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean lessThan(int val);
@@ -359,7 +359,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this <= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean lessOrEqual(int val);
@@ -369,7 +369,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this > val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean greaterThan(int val);
@@ -379,7 +379,7 @@
* @param val value to which this Signed is to be compared.
* @return {@code this >= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean greaterOrEqual(int val);
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/UnsignedWord.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/UnsignedWord.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,7 @@
/**
* Represents an unsigned word-sized value.
*
- * @since 1.0
+ * @since 19.0
*/
public interface UnsignedWord extends ComparableWord {
@@ -53,7 +53,7 @@
* @param val value to be added to this Unsigned.
* @return {@code this + val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord add(UnsignedWord val);
@@ -63,7 +63,7 @@
* @param val value to be subtracted from this Unsigned.
* @return {@code this - val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord subtract(UnsignedWord val);
@@ -73,7 +73,7 @@
* @param val value to be multiplied by this Unsigned.
* @return {@code this * val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord multiply(UnsignedWord val);
@@ -83,7 +83,7 @@
* @param val value by which this Unsigned is to be divided.
* @return {@code this / val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord unsignedDivide(UnsignedWord val);
@@ -93,7 +93,7 @@
* @param val value by which this Unsigned is to be divided, and the remainder computed.
* @return {@code this % val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord unsignedRemainder(UnsignedWord val);
@@ -103,7 +103,7 @@
* @param n shift distance, in bits.
* @return {@code this << n}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord shiftLeft(UnsignedWord n);
@@ -113,7 +113,7 @@
* @param n shift distance, in bits.
* @return {@code this >> n}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord unsignedShiftRight(UnsignedWord n);
@@ -123,7 +123,7 @@
* @param val value to be AND'ed with this Unsigned.
* @return {@code this & val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord and(UnsignedWord val);
@@ -133,7 +133,7 @@
* @param val value to be OR'ed with this Unsigned.
* @return {@code this | val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord or(UnsignedWord val);
@@ -143,7 +143,7 @@
* @param val value to be XOR'ed with this Unsigned.
* @return {@code this ^ val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord xor(UnsignedWord val);
@@ -152,7 +152,7 @@
*
* @return {@code ~this}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord not();
@@ -162,7 +162,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this == val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean equal(UnsignedWord val);
@@ -172,7 +172,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this != val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean notEqual(UnsignedWord val);
@@ -182,7 +182,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this < val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean belowThan(UnsignedWord val);
@@ -192,7 +192,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this <= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean belowOrEqual(UnsignedWord val);
@@ -202,7 +202,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this > val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean aboveThan(UnsignedWord val);
@@ -212,7 +212,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this >= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean aboveOrEqual(UnsignedWord val);
@@ -225,7 +225,7 @@
* @param val value to be added to this Unsigned.
* @return {@code this + val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord add(int val);
@@ -238,7 +238,7 @@
* @param val value to be subtracted from this Unsigned.
* @return {@code this - val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord subtract(int val);
@@ -251,7 +251,7 @@
* @param val value to be multiplied by this Unsigned.
* @return {@code this * val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord multiply(int val);
@@ -264,7 +264,7 @@
* @param val value by which this Unsigned is to be divided.
* @return {@code this / val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord unsignedDivide(int val);
@@ -277,7 +277,7 @@
* @param val value by which this Unsigned is to be divided, and the remainder computed.
* @return {@code this % val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord unsignedRemainder(int val);
@@ -290,7 +290,7 @@
* @param n shift distance, in bits.
* @return {@code this << n}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord shiftLeft(int n);
@@ -303,7 +303,7 @@
* @param n shift distance, in bits.
* @return {@code this >> n}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord unsignedShiftRight(int n);
@@ -316,7 +316,7 @@
* @param val value to be AND'ed with this Unsigned.
* @return {@code this & val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord and(int val);
@@ -329,7 +329,7 @@
* @param val value to be OR'ed with this Unsigned.
* @return {@code this | val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord or(int val);
@@ -342,7 +342,7 @@
* @param val value to be XOR'ed with this Unsigned.
* @return {@code this ^ val}
*
- * @since 1.0
+ * @since 19.0
*/
UnsignedWord xor(int val);
@@ -355,7 +355,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this == val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean equal(int val);
@@ -368,7 +368,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this != val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean notEqual(int val);
@@ -381,7 +381,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this < val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean belowThan(int val);
@@ -394,7 +394,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this <= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean belowOrEqual(int val);
@@ -407,7 +407,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this > val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean aboveThan(int val);
@@ -420,7 +420,7 @@
* @param val value to which this Unsigned is to be compared.
* @return {@code this >= val}
*
- * @since 1.0
+ * @since 19.0
*/
boolean aboveOrEqual(int val);
}
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordBase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordBase.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,14 +43,14 @@
/**
* The root of the interface hierarchy for machine-word-sized values.
*
- * @since 1.0
+ * @since 19.0
*/
public interface WordBase {
/**
* Conversion to a Java primitive value.
*
- * @since 1.0
+ * @since 19.0
*/
long rawValue();
@@ -59,7 +59,7 @@
* the other word based equality routines. In general you should never be statically calling
* this method anyway.
*
- * @since 1.0
+ * @since 19.0
*/
@Override
@Deprecated
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordFactory.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordFactory.java Fri Jun 28 14:36:42 2019 +0530
@@ -47,7 +47,7 @@
/**
* Provides factory method to create machine-word-sized values.
*
- * @since 1.0
+ * @since 19.0
*/
public final class WordFactory {
@@ -60,7 +60,7 @@
*
* @return the constant 0.
*
- * @since 1.0
+ * @since 19.0
*/
@WordFactoryOperation(opcode = WordFactoryOpcode.ZERO)
public static <T extends WordBase> T zero() {
@@ -73,7 +73,7 @@
*
* @return the null pointer.
*
- * @since 1.0
+ * @since 19.0
*/
@WordFactoryOperation(opcode = WordFactoryOpcode.ZERO)
public static <T extends PointerBase> T nullPointer() {
@@ -87,7 +87,7 @@
* @param val a 64 bit unsigned value
* @return the value cast to Word
*
- * @since 1.0
+ * @since 19.0
*/
@WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
public static <T extends UnsignedWord> T unsigned(long val) {
@@ -101,7 +101,7 @@
* @param val a 64 bit unsigned value
* @return the value cast to PointerBase
*
- * @since 1.0
+ * @since 19.0
*/
@WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
public static <T extends PointerBase> T pointer(long val) {
@@ -115,7 +115,7 @@
* @param val a 32 bit unsigned value
* @return the value cast to Word
*
- * @since 1.0
+ * @since 19.0
*/
@WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
public static <T extends UnsignedWord> T unsigned(int val) {
@@ -129,7 +129,7 @@
* @param val a 64 bit signed value
* @return the value cast to Word
*
- * @since 1.0
+ * @since 19.0
*/
@WordFactoryOperation(opcode = WordFactoryOpcode.FROM_SIGNED)
public static <T extends SignedWord> T signed(long val) {
@@ -143,7 +143,7 @@
* @param val a 32 bit signed value
* @return the value cast to Word
*
- * @since 1.0
+ * @since 19.0
*/
@WordFactoryOperation(opcode = WordFactoryOpcode.FROM_SIGNED)
public static <T extends SignedWord> T signed(int val) {
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,7 +29,7 @@
* This package provides a low-level mechanism to use machine-word-sized values in Java. The package
* can only be used in the context of native images or Graal snippets.
*
- * @since 1.0
+ * @since 19.0
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/BlackholeDirectiveTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/BlackholeDirectiveTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -139,7 +139,7 @@
}
@Override
- protected boolean checkLowTierGraph(StructuredGraph graph) {
+ protected void checkLowTierGraph(StructuredGraph graph) {
BlackholeSnippet snippet = graph.method().getAnnotation(BlackholeSnippet.class);
ParameterNode arg = graph.getParameter(0);
if (snippet.expectParameterUsage()) {
@@ -148,6 +148,5 @@
} else {
Assert.assertTrue("expected no usages of ParameterNode", arg == null || arg.hasNoUsages());
}
- return true;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -249,7 +249,7 @@
}
@Override
- protected boolean checkLowTierGraph(StructuredGraph graph) {
+ protected void checkLowTierGraph(StructuredGraph graph) {
List<ControlFlowAnchorNode> anchors = graph.getNodes().filter(ControlFlowAnchorNode.class).snapshot();
for (int i = 0; i < anchors.size(); i++) {
ControlFlowAnchorNode a = anchors.get(i);
@@ -265,6 +265,5 @@
NodeIterable<? extends Node> nodes = graph.getNodes().filter(nodeCount.nodeClass());
Assert.assertEquals(nodeCount.nodeClass().getSimpleName(), nodeCount.expectedCount(), nodes.count());
}
- return true;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IterationDirectiveTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IterationDirectiveTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -54,13 +54,11 @@
}
@Override
- protected boolean checkLowTierGraph(StructuredGraph graph) {
+ protected void checkLowTierGraph(StructuredGraph graph) {
NodeIterable<LoopBeginNode> loopBeginNodes = graph.getNodes(LoopBeginNode.TYPE);
Assert.assertEquals("LoopBeginNode count", 1, loopBeginNodes.count());
LoopBeginNode loopBeginNode = loopBeginNodes.first();
Assert.assertEquals("loop frequency of " + loopBeginNode, 128, loopBeginNode.loopFrequency(), 0);
-
- return true;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/OpaqueDirectiveTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/OpaqueDirectiveTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -138,11 +138,10 @@
}
@Override
- protected boolean checkLowTierGraph(StructuredGraph graph) {
+ protected void checkLowTierGraph(StructuredGraph graph) {
OpaqueSnippet snippet = graph.method().getAnnotation(OpaqueSnippet.class);
for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) {
Assert.assertEquals(snippet.expectedReturnNode(), returnNode.result().getClass());
}
- return true;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,6 +24,8 @@
package org.graalvm.compiler.api.directives.test;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.graph.iterators.NodeIterable;
@@ -37,6 +39,15 @@
public class ProbabilityDirectiveTest extends GraalCompilerTest {
+ /**
+ * Called before a test is compiled.
+ */
+ @Override
+ protected void before(ResolvedJavaMethod method) {
+ // don't let -Xcomp pollute profile
+ method.reprofile();
+ }
+
public static int branchProbabilitySnippet(int arg) {
if (GraalDirectives.injectBranchProbability(0.125, arg > 0)) {
GraalDirectives.controlFlowAnchor(); // prevent removal of the if
@@ -68,7 +79,7 @@
}
@Override
- protected boolean checkLowTierGraph(StructuredGraph graph) {
+ protected void checkLowTierGraph(StructuredGraph graph) {
NodeIterable<IfNode> ifNodes = graph.getNodes(IfNode.TYPE);
Assert.assertEquals("IfNode count", 1, ifNodes.count());
@@ -81,8 +92,6 @@
oneSuccessor = ifNode.falseSuccessor();
}
Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(oneSuccessor), 0);
-
- return true;
}
private static int returnValue(AbstractBeginNode b) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Fri Jun 28 14:36:42 2019 +0530
@@ -2963,17 +2963,17 @@
public void annotatePatchingImmediate(int pos, Instruction instruction, int operandSizeBits, int offsetBits, int shift) {
if (codePatchingAnnotationConsumer != null) {
- codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(pos, instruction, operandSizeBits, offsetBits, shift));
+ codePatchingAnnotationConsumer.accept(new SingleInstructionAnnotation(pos, instruction, operandSizeBits, offsetBits, shift));
}
}
- void annotatePatchingImmediateNativeAddress(int pos, int operandSizeBits, int numInstrs) {
+ void annotateImmediateMovSequence(int pos, int numInstrs) {
if (codePatchingAnnotationConsumer != null) {
- codePatchingAnnotationConsumer.accept(new MovSequenceAnnotation(pos, operandSizeBits, numInstrs));
+ codePatchingAnnotationConsumer.accept(new MovSequenceAnnotation(pos, numInstrs));
}
}
- public static class OperandDataAnnotation extends CodeAnnotation {
+ public static class SingleInstructionAnnotation extends CodeAnnotation {
/**
* The size of the operand, in bytes.
@@ -2983,7 +2983,7 @@
public final Instruction instruction;
public final int shift;
- OperandDataAnnotation(int instructionPosition, Instruction instruction, int operandSizeBits, int offsetBits, int shift) {
+ SingleInstructionAnnotation(int instructionPosition, Instruction instruction, int operandSizeBits, int offsetBits, int shift) {
super(instructionPosition);
this.operandSizeBits = operandSizeBits;
this.offsetBits = offsetBits;
@@ -2997,12 +2997,10 @@
/**
* The size of the operand, in bytes.
*/
- public final int operandSizeBits;
public final int numInstrs;
- MovSequenceAnnotation(int instructionPosition, int operandSizeBits, int numInstrs) {
+ MovSequenceAnnotation(int instructionPosition, int numInstrs) {
super(instructionPosition);
- this.operandSizeBits = operandSizeBits;
this.numInstrs = numInstrs;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java Fri Jun 28 14:36:42 2019 +0530
@@ -339,10 +339,13 @@
* Generates a 64-bit immediate move code sequence.
*
* @param dst general purpose register. May not be null, stackpointer or zero-register.
- * @param imm
+ * @param imm the value to move into the register
+ * @param annotateImm Flag denoting if annotation should be added.
*/
- private void mov64(Register dst, long imm) {
+ private void mov64(Register dst, long imm, boolean annotateImm) {
// We have to move all non zero parts of the immediate in 16-bit chunks
+ int numMovs = 0;
+ int pos = position();
boolean firstMove = true;
for (int offset = 0; offset < 64; offset += 16) {
int chunk = (int) (imm >> offset) & NumUtil.getNbitNumberInt(16);
@@ -355,8 +358,12 @@
} else {
movk(64, dst, chunk, offset);
}
+ ++numMovs;
}
assert !firstMove;
+ if (annotateImm) {
+ annotateImmediateMovSequence(pos, numMovs);
+ }
}
/**
@@ -378,7 +385,6 @@
*/
public void mov(Register dst, long imm, boolean annotateImm) {
assert dst.getRegisterCategory().equals(CPU);
- int pos = position();
if (imm == 0L) {
movx(dst, zr);
} else if (LogicalImmediateTable.isRepresentable(true, imm) != LogicalImmediateTable.Representable.NO) {
@@ -391,10 +397,7 @@
mov(dst, (int) imm);
sxt(64, 32, dst, dst);
} else {
- mov64(dst, imm);
- if (annotateImm) {
- annotatePatchingImmediateNativeAddress(pos, 64, 4);
- }
+ mov64(dst, imm, annotateImm);
}
}
@@ -448,7 +451,7 @@
}
}
if (annotateImm) {
- annotatePatchingImmediateNativeAddress(pos, 48, 3);
+ annotateImmediateMovSequence(pos, 3);
}
assert !firstMove;
}
@@ -1805,24 +1808,24 @@
}
/**
- * Emits elf patchable adrp add sequence.
+ * Emits elf patchable adrp ldr sequence.
*/
- public void adrAddRel(int srcSize, Register result, AArch64Address a) {
+ public void adrpLdr(int srcSize, Register result, AArch64Address a) {
if (codePatchingAnnotationConsumer != null) {
- codePatchingAnnotationConsumer.accept(new ADRADDPRELMacroInstruction(position()));
+ codePatchingAnnotationConsumer.accept(new AdrpLdrMacroInstruction(position()));
}
super.adrp(a.getBase());
this.ldr(srcSize, result, a);
}
- public static class ADRADDPRELMacroInstruction extends CodeAnnotation implements MacroInstruction {
- public ADRADDPRELMacroInstruction(int position) {
+ public static class AdrpLdrMacroInstruction extends CodeAnnotation implements MacroInstruction {
+ public AdrpLdrMacroInstruction(int position) {
super(position);
}
@Override
public String toString() {
- return "ADR_PREL_PG";
+ return "ADRP_LDR";
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64AsmOptions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64AsmOptions.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,6 +27,7 @@
public class AMD64AsmOptions {
public static final boolean UseNormalNop = false;
public static final boolean UseAddressNop = true;
+ public static final boolean UseIntelNops = true;
public static final boolean UseIncDec = true;
public static final boolean UseXmmLoadAndClearUpper = true;
public static final boolean UseXmmRegToRegMoveAll = true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,6 +29,7 @@
import static jdk.vm.ci.amd64.AMD64.XMM;
import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop;
+import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIntelNops;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.AND;
@@ -2295,125 +2296,10 @@
}
if (UseAddressNop) {
- //
- // Using multi-bytes nops "0x0F 0x1F [Address]" for AMD.
- // 1: 0x90
- // 2: 0x66 0x90
- // 3: 0x66 0x66 0x90 (don't use "0x0F 0x1F 0x00" - need patching safe padding)
- // 4: 0x0F 0x1F 0x40 0x00
- // 5: 0x0F 0x1F 0x44 0x00 0x00
- // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00
- // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
- // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
- // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
- // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
- // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
-
- // The rest coding is AMD specific - use consecutive Address nops
-
- // 12: 0x66 0x0F 0x1F 0x44 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00
- // 13: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00
- // 14: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
- // 15: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
- // 16: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
- // Size prefixes (0x66) are added for larger sizes
-
- while (i >= 22) {
- i -= 11;
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- addrNop8();
- }
- // Generate first nop for size between 21-12
- switch (i) {
- case 21:
- i -= 11;
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- addrNop8();
- break;
- case 20:
- case 19:
- i -= 10;
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- addrNop8();
- break;
- case 18:
- case 17:
- i -= 9;
- emitByte(0x66); // size prefix
- addrNop8();
- break;
- case 16:
- case 15:
- i -= 8;
- addrNop8();
- break;
- case 14:
- case 13:
- i -= 7;
- addrNop7();
- break;
- case 12:
- i -= 6;
- emitByte(0x66); // size prefix
- addrNop5();
- break;
- default:
- assert i < 12;
- }
-
- // Generate second nop for size between 11-1
- switch (i) {
- case 11:
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- addrNop8();
- break;
- case 10:
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- addrNop8();
- break;
- case 9:
- emitByte(0x66); // size prefix
- addrNop8();
- break;
- case 8:
- addrNop8();
- break;
- case 7:
- addrNop7();
- break;
- case 6:
- emitByte(0x66); // size prefix
- addrNop5();
- break;
- case 5:
- addrNop5();
- break;
- case 4:
- addrNop4();
- break;
- case 3:
- // Don't use "0x0F 0x1F 0x00" - need patching safe padding
- emitByte(0x66); // size prefix
- emitByte(0x66); // size prefix
- emitByte(0x90); // nop
- break;
- case 2:
- emitByte(0x66); // size prefix
- emitByte(0x90); // nop
- break;
- case 1:
- emitByte(0x90); // nop
- break;
- default:
- assert i == 0;
+ if (UseIntelNops) {
+ intelNops(i);
+ } else {
+ amdNops(i);
}
return;
}
@@ -2484,6 +2370,222 @@
}
}
+ private void amdNops(int count) {
+ int i = count;
+ //
+ // Using multi-bytes nops "0x0F 0x1F [Address]" for AMD.
+ // 1: 0x90
+ // 2: 0x66 0x90
+ // 3: 0x66 0x66 0x90 (don't use "0x0F 0x1F 0x00" - need patching safe padding)
+ // 4: 0x0F 0x1F 0x40 0x00
+ // 5: 0x0F 0x1F 0x44 0x00 0x00
+ // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00
+ // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
+ // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+ // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+ // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+ // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+
+ // The rest coding is AMD specific - use consecutive Address nops
+
+ // 12: 0x66 0x0F 0x1F 0x44 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00
+ // 13: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x66 0x0F 0x1F 0x44 0x00 0x00
+ // 14: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
+ // 15: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
+ // 16: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+ // Size prefixes (0x66) are added for larger sizes
+
+ while (i >= 22) {
+ i -= 11;
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ addrNop8();
+ }
+ // Generate first nop for size between 21-12
+ switch (i) {
+ case 21:
+ i -= 11;
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ addrNop8();
+ break;
+ case 20:
+ case 19:
+ i -= 10;
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ addrNop8();
+ break;
+ case 18:
+ case 17:
+ i -= 9;
+ emitByte(0x66); // size prefix
+ addrNop8();
+ break;
+ case 16:
+ case 15:
+ i -= 8;
+ addrNop8();
+ break;
+ case 14:
+ case 13:
+ i -= 7;
+ addrNop7();
+ break;
+ case 12:
+ i -= 6;
+ emitByte(0x66); // size prefix
+ addrNop5();
+ break;
+ default:
+ assert i < 12;
+ }
+
+ // Generate second nop for size between 11-1
+ switch (i) {
+ case 11:
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ addrNop8();
+ break;
+ case 10:
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ addrNop8();
+ break;
+ case 9:
+ emitByte(0x66); // size prefix
+ addrNop8();
+ break;
+ case 8:
+ addrNop8();
+ break;
+ case 7:
+ addrNop7();
+ break;
+ case 6:
+ emitByte(0x66); // size prefix
+ addrNop5();
+ break;
+ case 5:
+ addrNop5();
+ break;
+ case 4:
+ addrNop4();
+ break;
+ case 3:
+ // Don't use "0x0F 0x1F 0x00" - need patching safe padding
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x90); // nop
+ break;
+ case 2:
+ emitByte(0x66); // size prefix
+ emitByte(0x90); // nop
+ break;
+ case 1:
+ emitByte(0x90); // nop
+ break;
+ default:
+ assert i == 0;
+ }
+ }
+
+ @SuppressWarnings("fallthrough")
+ private void intelNops(int count) {
+ //
+ // Using multi-bytes nops "0x0F 0x1F [address]" for Intel
+ // 1: 0x90
+ // 2: 0x66 0x90
+ // 3: 0x66 0x66 0x90 (don't use "0x0F 0x1F 0x00" - need patching safe padding)
+ // 4: 0x0F 0x1F 0x40 0x00
+ // 5: 0x0F 0x1F 0x44 0x00 0x00
+ // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00
+ // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
+ // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+ // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+ // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+ // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
+
+ // The rest coding is Intel specific - don't use consecutive address nops
+
+ // 12: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90
+ // 13: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90
+ // 14: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90
+ // 15: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00 0x66 0x66 0x66 0x90
+
+ int i = count;
+ while (i >= 15) {
+ // For Intel don't generate consecutive addess nops (mix with regular nops)
+ i -= 15;
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ addrNop8();
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x90);
+ // nop
+ }
+ switch (i) {
+ case 14:
+ emitByte(0x66); // size prefix
+ // fall through
+ case 13:
+ emitByte(0x66); // size prefix
+ // fall through
+ case 12:
+ addrNop8();
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x66); // size prefix
+ emitByte(0x90);
+ // nop
+ break;
+ case 11:
+ emitByte(0x66); // size prefix
+ // fall through
+ case 10:
+ emitByte(0x66); // size prefix
+ // fall through
+ case 9:
+ emitByte(0x66); // size prefix
+ // fall through
+ case 8:
+ addrNop8();
+ break;
+ case 7:
+ addrNop7();
+ break;
+ case 6:
+ emitByte(0x66); // size prefix
+ // fall through
+ case 5:
+ addrNop5();
+ break;
+ case 4:
+ addrNop4();
+ break;
+ case 3:
+ // Don't use "0x0F 0x1F 0x00" - need patching safe padding
+ emitByte(0x66); // size prefix
+ // fall through
+ case 2:
+ emitByte(0x66); // size prefix
+ // fall through
+ case 1:
+ emitByte(0x90);
+ // nop
+ break;
+ default:
+ assert i == 0;
+ }
+ }
+
public final void orl(Register dst, Register src) {
OR.rmOp.emit(this, DWORD, dst, src);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Assembler.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,6 +30,8 @@
import java.util.Map;
import java.util.function.Consumer;
+import org.graalvm.compiler.debug.GraalError;
+
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.TargetDescription;
@@ -164,7 +166,7 @@
Label label = labelsWithPatches;
while (label != null) {
if (label.patchPositions != null) {
- throw new InternalError("Label used by instructions at following offsets has not been bound: " + label.patchPositions);
+ throw new GraalError("Label used by instructions at following offsets has not been bound: %s", label.patchPositions);
}
Label next = label.nextWithPatches;
label.nextWithPatches = null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,12 +24,13 @@
package org.graalvm.compiler.asm;
-import org.graalvm.compiler.core.common.NumUtil;
-
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
+import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.serviceprovider.BufferUtil;
+
/**
* Code buffer management for the assembler.
*/
@@ -48,7 +49,7 @@
public void setPosition(int position) {
assert position >= 0 && position <= data.limit();
- data.position(position);
+ BufferUtil.asBaseBuffer(data).position(position);
}
/**
@@ -93,7 +94,7 @@
byte[] newBuf = Arrays.copyOf(data.array(), length * 4);
ByteBuffer newData = ByteBuffer.wrap(newBuf);
newData.order(data.order());
- newData.position(data.position());
+ BufferUtil.asBaseBuffer(newData).position(data.position());
data = newData;
}
}
@@ -170,6 +171,6 @@
}
public void reset() {
- data.clear();
+ BufferUtil.asBaseBuffer(data).clear();
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Label.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,6 +26,8 @@
import java.util.ArrayList;
+import org.graalvm.compiler.debug.GraalError;
+
/**
* This class represents a label within assembly code.
*/
@@ -71,7 +73,9 @@
* {@link #addPatchAt(int, Assembler)}.
*/
protected void bind(int pos, Assembler asm) {
- assert pos >= 0;
+ if (pos < 0) {
+ throw new GraalError("Cannot bind label to negative position %d", pos);
+ }
this.position = pos;
if (patchPositions != null) {
for (int i = 0; i < patchPositions.size(); ++i) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DataSection.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,6 +33,7 @@
import java.util.function.BiConsumer;
import org.graalvm.compiler.code.DataSection.Data;
+import org.graalvm.compiler.serviceprovider.BufferUtil;
import jdk.vm.ci.code.site.DataSectionReference;
import jdk.vm.ci.meta.SerializableConstant;
@@ -376,11 +377,11 @@
assert buffer.remaining() >= sectionSize;
int start = buffer.position();
for (Data d : dataItems) {
- buffer.position(start + d.ref.getOffset());
+ BufferUtil.asBaseBuffer(buffer).position(start + d.ref.getOffset());
onEmit.accept(d.ref, d.getSize());
d.emit(buffer, patch);
}
- buffer.position(start + sectionSize);
+ BufferUtil.asBaseBuffer(buffer).position(start + sectionSize);
}
public Data findData(DataSectionReference ref) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited and affiliates. All rights reserved.
+ * 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 org.graalvm.compiler.core.aarch64.test;
+
+import org.graalvm.compiler.lir.LIRInstruction;
+import org.graalvm.compiler.lir.aarch64.AArch64BitFieldOp;
+import org.junit.Test;
+
+import java.util.function.Predicate;
+
+public class AArch64BitFieldTest extends AArch64MatchRuleTest {
+ private static final Predicate<LIRInstruction> predicate = op -> (op instanceof AArch64BitFieldOp);
+
+ private void testAndCheckLIR(String method, String negativeMethod, Object input) {
+ test(method, input);
+ checkLIR(method, predicate, 1);
+ test(negativeMethod, input);
+ checkLIR(negativeMethod, predicate, 0);
+ }
+
+ /**
+ * unsigned bit field extract int.
+ */
+ public static int extractInt(int input) {
+ return (input >>> 6) & 0xffff;
+ }
+
+ /**
+ * unsigned bit field extract int (negative cases).
+ */
+ public static int invalidExtractInt(int input) {
+ int result = 0;
+ result += ((input >>> 10) & 0xfff0); // Invalid mask
+ result += ((input >>> 2) & 0x7fffffff); // Bit field width too large
+ result += ((input >>> 16) & 0x1ffff); // Width + lsb exceeds limit
+ return result;
+ }
+
+ @Test
+ public void testExtractInt() {
+ testAndCheckLIR("extractInt", "invalidExtractInt", 0x12345678);
+ }
+
+ /**
+ * unsigned bit field extract long.
+ */
+ public static long extractLong(long input) {
+ return (input >>> 25) & 0xffffffffL;
+ }
+
+ /**
+ * unsigned bit field extract long (negative cases).
+ */
+ public static long invalidExtractLong(long input) {
+ long result = 0L;
+ result += ((input >>> 10) & 0x230L); // Invalid mask
+ result += ((input >>> 2) & 0x7fffffffffffffffL); // Bit field width too large
+ result += ((input >>> 62) & 0x7L); // Width + lsb exceeds limit
+ return result;
+ }
+
+ @Test
+ public void testExtractLong() {
+ testAndCheckLIR("extractLong", "invalidExtractLong", 0xfedcba9876543210L);
+ }
+
+ /**
+ * unsigned bit field insert int.
+ */
+ public static int insertInt(int input) {
+ return (input & 0xfff) << 10;
+ }
+
+ /**
+ * unsigned bit field insert int (negative cases).
+ */
+ public static int invalidInsertInt(int input) {
+ int result = 0;
+ result += ((input & 0xe) << 25); // Invalid mask
+ result += ((input & 0x7fffffff) << 1); // Bit field width too large
+ result += ((input & 0x1ffff) << 16); // Width + lsb exceeds limit
+ return result;
+ }
+
+ @Test
+ public void testInsertInt() {
+ testAndCheckLIR("insertInt", "invalidInsertInt", 0xcafebabe);
+ }
+
+ /**
+ * unsigned bit field insert long.
+ */
+ public static long insertLong(long input) {
+ return (input & 0x3fffffffffffL) << 7;
+ }
+
+ /**
+ * unsigned bit field insert long (negative cases).
+ */
+ public static long invalidInsertLong(long input) {
+ long result = 0L;
+ result += ((input & 0x1a) << 39); // Invalid mask
+ result += ((input & 0x7fffffffffffffffL) << 1); // Bit field width too large
+ result += ((input & 0x3fffffff) << 52); // Width + lsb exceeds limit
+ return result;
+ }
+
+ @Test
+ public void testInsertLong() {
+ testAndCheckLIR("insertLong", "invalidInsertLong", 0xdeadbeefdeadbeefL);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,6 +26,7 @@
package org.graalvm.compiler.core.aarch64;
import jdk.vm.ci.aarch64.AArch64Kind;
+import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.AllocatableValue;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
@@ -42,6 +43,7 @@
import org.graalvm.compiler.lir.LabelRef;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
+import org.graalvm.compiler.lir.aarch64.AArch64BitFieldOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.ConstantNode;
@@ -65,7 +67,7 @@
public class AArch64NodeMatchRules extends NodeMatchRules {
private static final EconomicMap<Class<? extends Node>, AArch64ArithmeticOp> nodeOpMap;
-
+ private static final EconomicMap<Class<? extends BinaryNode>, AArch64BitFieldOp.BitFieldOpCode> bitFieldOpMap;
private static final EconomicMap<Class<? extends BinaryNode>, AArch64MacroAssembler.ShiftType> shiftTypeMap;
static {
@@ -76,6 +78,10 @@
nodeOpMap.put(OrNode.class, AArch64ArithmeticOp.OR);
nodeOpMap.put(XorNode.class, AArch64ArithmeticOp.XOR);
+ bitFieldOpMap = EconomicMap.create(Equivalence.IDENTITY, 2);
+ bitFieldOpMap.put(UnsignedRightShiftNode.class, AArch64BitFieldOp.BitFieldOpCode.UBFX);
+ bitFieldOpMap.put(LeftShiftNode.class, AArch64BitFieldOp.BitFieldOpCode.UBFIZ);
+
shiftTypeMap = EconomicMap.create(Equivalence.IDENTITY, 3);
shiftTypeMap.put(LeftShiftNode.class, AArch64MacroAssembler.ShiftType.LSL);
shiftTypeMap.put(RightShiftNode.class, AArch64MacroAssembler.ShiftType.ASR);
@@ -101,6 +107,19 @@
return getLIRGeneratorTool().moveSp(value);
}
+ private ComplexMatchResult emitBitField(AArch64BitFieldOp.BitFieldOpCode op, ValueNode value, int lsb, int width) {
+ assert op != null;
+ assert value.getStackKind().isNumericInteger();
+
+ return builder -> {
+ Value a = operand(value);
+ Variable result = gen.newVariable(LIRKind.combine(a));
+ AllocatableValue src = moveSp(gen.asAllocatable(a));
+ gen.append(new AArch64BitFieldOp(op, result, src, lsb, width));
+ return result;
+ };
+ }
+
private ComplexMatchResult emitBinaryShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift,
boolean isShiftNot) {
AArch64MacroAssembler.ShiftType shiftType = shiftTypeMap.get(shift.getClass());
@@ -133,6 +152,40 @@
};
}
+ @MatchRule("(And (UnsignedRightShift=shift a Constant=b) Constant=c)")
+ @MatchRule("(LeftShift=shift (And a Constant=c) Constant=b)")
+ public ComplexMatchResult unsignedBitField(BinaryNode shift, ValueNode a, ConstantNode b, ConstantNode c) {
+ JavaKind srcKind = a.getStackKind();
+ assert srcKind.isNumericInteger();
+ AArch64BitFieldOp.BitFieldOpCode op = bitFieldOpMap.get(shift.getClass());
+ assert op != null;
+ int distance = b.asJavaConstant().asInt();
+ long mask = c.asJavaConstant().asLong();
+
+ // The Java(R) Language Specification CHAPTER 15.19 Shift Operators says:
+ // "If the promoted type of the left-hand operand is int(long), then only the five(six)
+ // lowest-order bits of the right-hand operand are used as the shift distance."
+ distance = distance & (srcKind == JavaKind.Int ? 0x1f : 0x3f);
+
+ // Constraint 1: Mask plus one should be a power-of-2 integer.
+ if (!CodeUtil.isPowerOf2(mask + 1)) {
+ return null;
+ }
+ int width = CodeUtil.log2(mask + 1);
+ int srcBits = srcKind.getBitCount();
+ // Constraint 2: Bit field width is less than 31(63) for int(long) as any bit field move
+ // operations can be done by a single shift instruction if the width is 31(63).
+ if (width >= srcBits - 1) {
+ return null;
+ }
+ // Constraint 3: Sum of bit field width and the shift distance is less or equal to 32(64)
+ // for int(long) as the specification of AArch64 bit field instructions.
+ if (width + distance > srcBits) {
+ return null;
+ }
+ return emitBitField(op, a, distance, width);
+ }
+
@MatchRule("(Add=binary a (LeftShift=shift b Constant))")
@MatchRule("(Add=binary a (RightShift=shift b Constant))")
@MatchRule("(Add=binary a (UnsignedRightShift=shift b Constant))")
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -450,6 +450,13 @@
}
}
+ public Value emitBinaryMemory(VexRVMOp op, OperandSize size, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
+ assert (size.isXmmType() && supportAVX());
+ Variable result = getLIRGen().newVariable(LIRKind.combine(a));
+ getLIRGen().append(new AMD64VectorBinary.AVXBinaryMemoryOp(op, getRegisterSize(result), result, a, location, state));
+ return result;
+ }
+
public Value emitBinaryMemory(AMD64RMOp op, OperandSize size, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) {
Variable result = getLIRGen().newVariable(LIRKind.combine(a));
getLIRGen().append(new AMD64Binary.MemoryTwoOp(op, size, result, a, location, state));
@@ -1339,7 +1346,7 @@
return result;
}
- private boolean supportAVX() {
+ public boolean supportAVX() {
TargetDescription target = getLIRGen().target();
return ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -576,13 +576,10 @@
}
@Override
- public Variable emitArrayIndexOf(JavaKind kind, boolean findTwoConsecutive, Value arrayPointer, Value arrayLength, Value... searchValues) {
- Variable result = newVariable(LIRKind.value(AMD64Kind.QWORD));
- Value[] allocatableSearchValues = new Value[searchValues.length];
- for (int i = 0; i < searchValues.length; i++) {
- allocatableSearchValues[i] = asAllocatable(searchValues[i]);
- }
- append(new AMD64ArrayIndexOfOp(kind, findTwoConsecutive, getVMPageSize(), getMaxVectorSize(), this, result, asAllocatable(arrayPointer), asAllocatable(arrayLength), allocatableSearchValues));
+ public Variable emitArrayIndexOf(JavaKind arrayKind, JavaKind valueKind, boolean findTwoConsecutive, Value arrayPointer, Value arrayLength, Value fromIndex, Value... searchValues) {
+ Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
+ append(new AMD64ArrayIndexOfOp(arrayKind, valueKind, findTwoConsecutive, getMaxVectorSize(), this, result,
+ asAllocatable(arrayPointer), asAllocatable(arrayLength), asAllocatable(fromIndex), searchValues));
return result;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,11 +33,18 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSX;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXB;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSS;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VSUBSD;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VSUBSS;
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.DWORD;
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.QWORD;
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SD;
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SS;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
@@ -380,7 +387,7 @@
@MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))")
public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) {
assert compare.condition() == CanonicalCondition.EQ;
- if (value == cas.getExpectedValue() && cas.usages().count() == 1) {
+ if (value == cas.getExpectedValue() && cas.hasExactlyOneUsage()) {
return builder -> {
LIRKind kind = getLirKind(cas);
LabelRef trueLabel = getLIRBlock(root.trueSuccessor());
@@ -403,7 +410,7 @@
public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) {
JavaConstant constant = value.asJavaConstant();
assert compare.condition() == CanonicalCondition.EQ;
- if (constant != null && cas.usages().count() == 1) {
+ if (constant != null && cas.hasExactlyOneUsage()) {
long constantValue = constant.asLong();
boolean successIsTrue;
if (constantValue == 0) {
@@ -463,12 +470,22 @@
getState(access));
}
+ private ComplexMatchResult binaryRead(AMD64Assembler.VexRVMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) {
+ assert size == SS || size == SD;
+ return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()),
+ getState(access));
+ }
+
@MatchRule("(Add value Read=access)")
@MatchRule("(Add value FloatingRead=access)")
public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) {
OperandSize size = getMemorySize(access);
if (size.isXmmType()) {
- return binaryRead(SSEOp.ADD, size, value, access);
+ if (getArithmeticLIRGenerator().supportAVX()) {
+ return binaryRead(size == SS ? VADDSS : VADDSD, size, value, access);
+ } else {
+ return binaryRead(SSEOp.ADD, size, value, access);
+ }
} else {
return binaryRead(ADD.getRMOpcode(size), size, value, access);
}
@@ -479,7 +496,11 @@
public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) {
OperandSize size = getMemorySize(access);
if (size.isXmmType()) {
- return binaryRead(SSEOp.SUB, size, value, access);
+ if (getArithmeticLIRGenerator().supportAVX()) {
+ return binaryRead(size == SS ? VSUBSS : VSUBSD, size, value, access);
+ } else {
+ return binaryRead(SSEOp.SUB, size, value, access);
+ }
} else {
return binaryRead(SUB.getRMOpcode(size), size, value, access);
}
@@ -490,7 +511,11 @@
public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) {
OperandSize size = getMemorySize(access);
if (size.isXmmType()) {
- return binaryRead(SSEOp.MUL, size, value, access);
+ if (getArithmeticLIRGenerator().supportAVX()) {
+ return binaryRead(size == SS ? VMULSS : VMULSD, size, value, access);
+ } else {
+ return binaryRead(SSEOp.MUL, size, value, access);
+ }
} else {
return binaryRead(AMD64RMOp.IMUL, size, value, access);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,10 +26,11 @@
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionStability;
import org.graalvm.compiler.options.OptionType;
/**
- * This class encapsulates options that control the behavior of the Graal compiler.
+ * This class encapsulates options that control the behavior of the GraalVM compiler.
*/
// @formatter:off
public final class GraalOptions {
@@ -167,6 +168,9 @@
public static final OptionKey<Boolean> ConditionalElimination = new OptionKey<>(true);
@Option(help = "", type = OptionType.Debug)
+ public static final OptionKey<Integer> ConditionalEliminationMaxIterations = new OptionKey<>(4);
+
+ @Option(help = "", type = OptionType.Debug)
public static final OptionKey<Boolean> RawConditionalElimination = new OptionKey<>(true);
@Option(help = "", type = OptionType.Debug)
@@ -238,9 +242,6 @@
public static final OptionKey<Boolean> OptImplicitNullChecks = new OptionKey<>(true);
@Option(help = "", type = OptionType.Debug)
- public static final OptionKey<Boolean> OptClearNonLiveLocals = new OptionKey<>(true);
-
- @Option(help = "", type = OptionType.Debug)
public static final OptionKey<Boolean> OptLoopTransform = new OptionKey<>(true);
@Option(help = "", type = OptionType.Debug)
@@ -273,7 +274,7 @@
@Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug)
public static final OptionKey<Boolean> UseSnippetGraphCache = new OptionKey<>(true);
- @Option(help = "file:doc-files/TraceInliningHelp.txt", type = OptionType.Debug)
+ @Option(help = "file:doc-files/TraceInliningHelp.txt", type = OptionType.Debug, stability = OptionStability.STABLE)
public static final OptionKey<Boolean> TraceInlining = new OptionKey<>(false);
@Option(help = "Enable inlining decision tracing in stubs and snippets.", type = OptionType.Debug)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java Fri Jun 28 14:36:42 2019 +0530
@@ -88,7 +88,7 @@
this.referenceCompressionMask = referenceCompressionMask;
this.derivedReferenceBase = derivedReferenceBase;
- assert this.referenceCompressionMask == 0 || this.referenceMask == this.referenceCompressionMask : "mixing compressed and uncompressed references is untested";
+ assert this.referenceCompressionMask == 0 || this.referenceMask == this.referenceCompressionMask : "mixing compressed and uncompressed references is unsupported";
assert derivedReferenceBase == null || !derivedReferenceBase.getValueKind(LIRKind.class).isDerivedReference() : "derived reference can't have another derived reference as base";
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,6 +27,7 @@
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionStability;
import org.graalvm.compiler.options.OptionType;
public enum SpeculativeExecutionAttacksMitigations {
@@ -39,7 +40,7 @@
// @formatter:off
@Option(help = "file:doc-files/MitigateSpeculativeExecutionAttacksHelp.txt")
public static final EnumOptionKey<SpeculativeExecutionAttacksMitigations> MitigateSpeculativeExecutionAttacks = new EnumOptionKey<>(None);
- @Option(help = "Use index masking after bounds check to mitigate speculative execution attacks.", type = OptionType.User)
+ @Option(help = "Use index masking after bounds check to mitigate speculative execution attacks.", type = OptionType.User, stability = OptionStability.STABLE)
public static final OptionKey<Boolean> UseIndexMasking = new OptionKey<>(false);
// @formatter:on
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Fri Jun 28 14:36:42 2019 +0530
@@ -150,6 +150,13 @@
}
/**
+ * Returns true if NaN is included in the value described by this stamp.
+ */
+ public boolean canBeNaN() {
+ return !nonNaN;
+ }
+
+ /**
* Returns true if this stamp represents the NaN value.
*/
public boolean isNaN() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java Fri Jun 28 14:36:42 2019 +0530
@@ -151,7 +151,7 @@
public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) {
JavaConstant constant = value.asJavaConstant();
assert compare.condition() == CanonicalCondition.EQ;
- if (constant != null && cas.usages().count() == 1) {
+ if (constant != null && cas.hasExactlyOneUsage()) {
long constantValue = constant.asLong();
boolean successIsTrue;
if (constantValue == 0) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CanonicalizedConversionTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CanonicalizedConversionTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -41,7 +41,7 @@
public class CanonicalizedConversionTest extends GraalCompilerTest {
@Override
- protected boolean checkLowTierGraph(StructuredGraph graph) {
+ protected void checkLowTierGraph(StructuredGraph graph) {
int reinterpretCount = 0;
int floatEqualsCount = 0;
int addCount = 0;
@@ -59,7 +59,6 @@
Assert.assertEquals(1, reinterpretCount);
Assert.assertEquals(1, floatEqualsCount);
Assert.assertEquals(2, addCount);
- return true;
}
@Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Fri Jun 28 14:36:42 2019 +0530
@@ -66,6 +66,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.PhaseSuite;
@@ -73,9 +74,9 @@
import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
import org.graalvm.compiler.phases.contract.VerifyNodeCosts;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.internal.vm.compiler.word.LocationIdentity;
import org.junit.Assert;
import org.junit.Assume;
@@ -127,7 +128,7 @@
protected String getClassPath() {
String bootclasspath;
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
bootclasspath = System.getProperty("sun.boot.class.path");
} else {
bootclasspath = System.getProperty("jdk.module.path") + File.pathSeparatorChar + System.getProperty("jdk.module.upgrade.path");
@@ -139,7 +140,7 @@
if (className.equals("module-info") || className.startsWith("META-INF.versions.")) {
return false;
}
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
// @formatter:off
/*
* Work around to prevent:
@@ -247,7 +248,7 @@
List<String> errors = Collections.synchronizedList(new ArrayList<>());
- List<VerifyPhase<PhaseContext>> verifiers = new ArrayList<>();
+ List<VerifyPhase<CoreProviders>> verifiers = new ArrayList<>();
// If you add a new type to test here, be sure to add appropriate
// methods to the BadUsageWithEquals class below
@@ -270,6 +271,7 @@
verifiers.add(new VerifySystemPropertyUsage());
verifiers.add(new VerifyInstanceOfUsage());
verifiers.add(new VerifyGraphAddUsage());
+ verifiers.add(new VerifyBufferUsage());
verifiers.add(new VerifyGetOptionsUsage());
verifiers.add(new VerifyUnsafeAccess());
@@ -413,14 +415,14 @@
* @param metaAccess
* @param verifiers
*/
- private static void checkClass(Class<?> c, MetaAccessProvider metaAccess, List<VerifyPhase<PhaseContext>> verifiers) {
+ private static void checkClass(Class<?> c, MetaAccessProvider metaAccess, List<VerifyPhase<CoreProviders>> verifiers) {
if (Node.class.isAssignableFrom(c)) {
if (c.getAnnotation(NodeInfo.class) == null) {
throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName()));
}
VerifyNodeCosts.verifyNodeClass(c);
}
- for (VerifyPhase<PhaseContext> verifier : verifiers) {
+ for (VerifyPhase<CoreProviders> verifier : verifiers) {
verifier.verifyClass(c, metaAccess);
}
}
@@ -445,8 +447,8 @@
/**
* Checks the invariants for a single graph.
*/
- private static void checkGraph(List<VerifyPhase<PhaseContext>> verifiers, HighTierContext context, StructuredGraph graph) {
- for (VerifyPhase<PhaseContext> verifier : verifiers) {
+ private static void checkGraph(List<VerifyPhase<CoreProviders>> verifiers, HighTierContext context, StructuredGraph graph) {
+ for (VerifyPhase<CoreProviders> verifier : verifiers) {
if (!(verifier instanceof VerifyUsageWithEquals) || shouldVerifyEquals(graph.method())) {
verifier.apply(graph, context);
} else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,8 +24,6 @@
package org.graalvm.compiler.core.test;
-import org.junit.Test;
-
import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -34,13 +32,13 @@
import org.graalvm.compiler.nodes.calc.ConditionalNode;
import org.graalvm.compiler.nodes.calc.IntegerTestNode;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Test;
public class CompareCanonicalizerTest extends GraalCompilerTest {
private StructuredGraph getCanonicalizedGraph(String name) {
StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
return graph;
}
@@ -57,7 +55,7 @@
StructuredGraph graph = parseEager("canonicalCompare" + i, AllowAssumptions.NO);
assertEquals(referenceGraph, graph);
}
- new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(referenceGraph, getProviders());
for (int i = 1; i < 4; i++) {
StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
assertEquals(referenceGraph, graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,7 +27,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class CompareCanonicalizerTest2 extends GraalCompilerTest {
@@ -36,7 +35,7 @@
private StructuredGraph getCanonicalizedGraph(String name) {
StructuredGraph graph = getRegularGraph(name);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
return graph;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,12 +29,12 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase;
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Ignore;
import org.junit.Test;
@@ -238,7 +238,7 @@
protected void assertCanonicallyEqual(String snippet, String reference) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
canonicalizer.apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,11 +28,11 @@
import org.graalvm.compiler.nodes.GuardNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -94,7 +94,7 @@
private void test(String snippet, int guardCount) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new ConditionalEliminationPhase(true).apply(graph, context);
Assert.assertEquals(guardCount, graph.getNodes().filter(GuardNode.class).count());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,8 +29,8 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Ignore;
import org.junit.Test;
@@ -310,7 +310,7 @@
}
@Override
- protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) {
+ protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, CoreProviders context, boolean applyLowering) {
super.prepareGraph(graph, canonicalizer, context, applyLowering);
graph.clearAllStateAfter();
graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest14.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest14.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,12 +35,12 @@
import org.graalvm.compiler.nodes.java.LoadIndexedNode;
import org.graalvm.compiler.nodes.memory.FloatingReadNode;
import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.FloatingReadPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -71,7 +71,7 @@
public void test1() {
StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.YES);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
/* Convert the LoadIndexNode to ReadNode with floating guards. */
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest15.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest15.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,11 +29,11 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase;
import org.junit.Assert;
import org.junit.Test;
@@ -48,7 +48,7 @@
StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
canonicalizer.apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest16.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest16.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,6 +32,7 @@
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.junit.Before;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -41,6 +42,13 @@
*/
public class ConditionalEliminationTest16 extends ConditionalEliminationTestBase {
+ @Before
+ public void resetType() {
+ parameterType = null;
+ }
+
+ Class<?> parameterType;
+
public static int testCastExactInstance(Object object) {
if (object.getClass() == Integer.class) {
return ((Integer) object).intValue();
@@ -50,35 +58,91 @@
}
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
- for (ParameterNode param : graph.getNodes().filter(ParameterNode.class)) {
- if (param.index() == 0) {
- ParameterNode newParam = new ParameterNode(0, StampPair.createSingle(StampFactory.object(TypeReference.createExactTrusted(getMetaAccess().lookupJavaType(Integer.class)))));
- graph.addWithoutUnique(newParam);
- param.replaceAtUsages(newParam);
- param.safeDelete();
- break;
+ protected void checkHighTierGraph(StructuredGraph graph) {
+ if (parameterType != null) {
+ for (ParameterNode param : graph.getNodes().filter(ParameterNode.class)) {
+ if (param.index() == 0) {
+ ParameterNode newParam = new ParameterNode(0, StampPair.createSingle(StampFactory.object(TypeReference.createExactTrusted(getMetaAccess().lookupJavaType(parameterType)))));
+ graph.addWithoutUnique(newParam);
+ param.replaceAtUsages(newParam);
+ param.safeDelete();
+ break;
+ }
}
+ new CanonicalizerPhase().apply(graph, getDefaultHighTierContext());
}
- new CanonicalizerPhase().apply(graph, getDefaultHighTierContext());
- return super.checkHighTierGraph(graph);
+ super.checkHighTierGraph(graph);
}
@Override
- protected boolean checkMidTierGraph(StructuredGraph graph) {
+ protected void checkMidTierGraph(StructuredGraph graph) {
int count = 0;
for (PiNode node : graph.getNodes().filter(PiNode.class)) {
assertTrue(node.getGuard() != null, "must have guarding node");
count++;
}
assertTrue(count > 0, "expected at least one Pi");
- return super.checkMidTierGraph(graph);
+ super.checkMidTierGraph(graph);
}
@Test
public void test1() {
+ parameterType = Integer.class;
ResolvedJavaMethod method = getResolvedJavaMethod("testCastExactInstance");
StructuredGraph graph = parseForCompile(method);
compile(method, graph);
}
+
+ static class Base {
+ int getValue1() {
+ return 0;
+ }
+
+ Base getBase() {
+ return this;
+ }
+ }
+
+ static class Box extends Base {
+ int value1;
+
+ @Override
+ int getValue1() {
+ return value1;
+ }
+ }
+
+ static class BiggerBox extends Box {
+ int value2;
+
+ int getValue2() {
+ return value2;
+ }
+ }
+
+ public static int testCastExactTwiceInstance(Base base, boolean b) {
+ if (!(base instanceof Box)) {
+ GraalDirectives.deoptimizeAndInvalidate();
+ return -1;
+ }
+ int total = 0;
+ if (base instanceof Box) {
+ Box box = (Box) base;
+ total += box.value1;
+ if (b) {
+ total += System.identityHashCode(base);
+ }
+ total += ((BiggerBox) base).getValue2();
+ }
+ return total;
+ }
+
+ @Test
+ public void test2() {
+ BiggerBox box = new BiggerBox();
+ ResolvedJavaMethod method = getResolvedJavaMethod("testCastExactTwiceInstance");
+ StructuredGraph graph = parseForCompile(method);
+ compile(method, graph);
+ test("testCastExactTwiceInstance", box, false);
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,12 +29,12 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.java.InstanceOfNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.FloatingReadPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -110,7 +110,7 @@
public void testRedundantCompares() {
StructuredGraph graph = parseEager("testRedundantComparesSnippet", AllowAssumptions.YES);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
canonicalizer.apply(graph, context);
@@ -133,7 +133,7 @@
StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", AllowAssumptions.YES);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
canonicalizer.apply(graph, context);
@@ -147,7 +147,7 @@
StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
canonicalizer.apply(graph, context);
new ConditionalEliminationPhase(true).apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,20 +25,20 @@
package org.graalvm.compiler.core.test;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.nodes.ProxyNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
-import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
/**
@@ -68,7 +68,7 @@
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
DebugContext debug = graph.getDebug();
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest", graph)) {
@@ -93,7 +93,7 @@
assertEquals(referenceGraph, graph);
}
- protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) {
+ protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, CoreProviders context, boolean applyLowering) {
if (applyLowering) {
new ConvertDeoptimizeToGuardPhase().apply(graph, context);
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
@@ -105,7 +105,7 @@
public void testProxies(String snippet, int expectedProxiesCreated) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase();
canonicalizer1.disableSimplification();
canonicalizer1.apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CopyOfVirtualizationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CopyOfVirtualizationTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,9 +35,9 @@
public class CopyOfVirtualizationTest extends GraalCompilerTest {
@Override
- protected boolean checkMidTierGraph(StructuredGraph graph) {
+ protected void checkMidTierGraph(StructuredGraph graph) {
assertTrue(graph.getNodes().filter(node -> node instanceof NewArrayNode).count() == 0, "shouldn't require allocation in %s", graph);
- return super.checkMidTierGraph(graph);
+ super.checkMidTierGraph(graph);
}
public byte byteCopyOfVirtualization(int index) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -483,14 +483,13 @@
}
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
+ protected void checkHighTierGraph(StructuredGraph graph) {
LoopsData loops = new LoopsData(graph);
loops.detectedCountedLoops();
for (IVPropertyNode node : graph.getNodes().filter(IVPropertyNode.class)) {
node.rewrite(loops);
}
assert graph.getNodes().filter(IVPropertyNode.class).isEmpty();
- return true;
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CustomizedBytecodePatternTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CustomizedBytecodePatternTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,14 +24,45 @@
package org.graalvm.compiler.core.test;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.objectweb.asm.Opcodes;
+import sun.misc.Unsafe;
+
public abstract class CustomizedBytecodePatternTest extends GraalCompilerTest implements Opcodes {
protected Class<?> getClass(String className) throws ClassNotFoundException {
return new CachedLoader(CustomizedBytecodePatternTest.class.getClassLoader(), className).findClass(className);
}
+ /**
+ * @param className
+ * @param lookUp lookup object with boot class load capability (required for jdk 9 and above)
+ * @return loaded class
+ * @throws ClassNotFoundException
+ */
+ protected Class<?> getClassBL(String className, MethodHandles.Lookup lookUp) throws ClassNotFoundException {
+ byte[] gen = generateClass(className.replace('.', '/'));
+ Method defineClass = null;
+ Class<?> loadedClass = null;
+ try {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
+ defineClass = Unsafe.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class);
+ loadedClass = (Class<?>) defineClass.invoke(UNSAFE, className, gen, 0, gen.length, null, null);
+ } else {
+ defineClass = MethodHandles.lookup().getClass().getDeclaredMethod("defineClass", byte[].class);
+ loadedClass = (Class<?>) defineClass.invoke(lookUp, gen);
+ }
+ } catch (Exception e) {
+ throw new ClassNotFoundException();
+ }
+ return loadedClass;
+ }
+
private class CachedLoader extends ClassLoader {
final String className;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,11 +32,11 @@
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.extended.MonitorExit;
import org.graalvm.compiler.nodes.memory.FloatingReadNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.FloatingReadPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -67,7 +67,7 @@
try (DebugContext.Scope s = debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new FloatingReadPhase().apply(graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -124,6 +124,7 @@
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.AddExports;
import org.graalvm.compiler.test.GraalTest;
import org.graalvm.compiler.test.JLModule;
@@ -150,9 +151,9 @@
import jdk.vm.ci.meta.SpeculationLog;
/**
- * Base class for Graal compiler unit tests.
+ * Base class for compiler unit tests.
* <p>
- * White box tests for Graal compiler transformations use this pattern:
+ * White box tests for compiler transformations use this pattern:
* <ol>
* <li>Create a graph by {@linkplain #parseEager parsing} a method.</li>
* <li>Manually modify the graph (e.g. replace a parameter node with a constant).</li>
@@ -194,7 +195,7 @@
* as of JDK 9.
*/
protected final void exportPackage(Class<?> moduleMember, String packageName) {
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
JLModule.exportPackageTo(moduleMember, packageName, getClass());
}
}
@@ -224,27 +225,27 @@
* Can be overridden by unit tests to verify properties of the graph.
*
* @param graph the graph at the end of HighTier
+ * @throws AssertionError if the verification fails
*/
- protected boolean checkHighTierGraph(StructuredGraph graph) {
- return true;
+ protected void checkHighTierGraph(StructuredGraph graph) {
}
/**
* Can be overridden by unit tests to verify properties of the graph.
*
* @param graph the graph at the end of MidTier
+ * @throws AssertionError if the verification fails
*/
- protected boolean checkMidTierGraph(StructuredGraph graph) {
- return true;
+ protected void checkMidTierGraph(StructuredGraph graph) {
}
/**
* Can be overridden by unit tests to verify properties of the graph.
*
* @param graph the graph at the end of LowTier
+ * @throws AssertionError if the verification fails
*/
- protected boolean checkLowTierGraph(StructuredGraph graph) {
- return true;
+ protected void checkLowTierGraph(StructuredGraph graph) {
}
protected static void breakpoint() {
@@ -288,7 +289,7 @@
@Override
protected void run(StructuredGraph graph) {
- assert checkHighTierGraph(graph) : "failed HighTier graph check";
+ checkHighTierGraph(graph);
}
@Override
@@ -305,7 +306,7 @@
@Override
protected void run(StructuredGraph graph) {
- assert checkMidTierGraph(graph) : "failed MidTier graph check";
+ checkMidTierGraph(graph);
}
@Override
@@ -322,7 +323,7 @@
@Override
protected void run(StructuredGraph graph) {
- assert checkLowTierGraph(graph) : "failed LowTier graph check";
+ checkLowTierGraph(graph);
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -34,8 +34,8 @@
import org.graalvm.compiler.nodes.GraphEncoder;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -60,7 +60,7 @@
if (javaMethod.hasBytecodes()) {
StructuredGraph originalGraph = parseEager(javaMethod, AllowAssumptions.YES);
if (canonicalize) {
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new CanonicalizerPhase().apply(originalGraph, context);
}
originalGraphs.add(originalGraph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.core.test;
-
-import java.util.List;
-
-import org.graalvm.compiler.core.common.CompilationIdentifier;
-import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.nodes.ConstantNode;
-import org.graalvm.compiler.nodes.Invoke;
-import org.graalvm.compiler.nodes.InvokeNode;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.OpaqueNode;
-import org.graalvm.compiler.nodes.extended.LoadHubNode;
-import org.graalvm.compiler.nodes.extended.LoadMethodNode;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
-import org.graalvm.compiler.options.OptionValues;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-/**
- * Tests use of an intrinsic for virtual methods where the call site is indirect. A prime example is
- * an intrinsic for {@link Object#hashCode()}. The intrinsic can only be used if the call site would
- * actually dispatch to {@link Object#hashCode()} and not a method that overrides it.
- */
-public class GuardedIntrinsicTest extends GraalCompilerTest {
-
- static class Super {
- int getAge() {
- return 11;
- }
- }
-
- public static class Person extends Super {
- int age;
-
- public Person(int age) {
- this.age = age;
- }
-
- @Override
- public int getAge() {
- return age;
- }
- }
-
- @BytecodeParserForceInline
- public static final Super createSuper() {
- return new Super();
- }
-
- @BytecodeParserNeverInline
- public static final Super createPerson() {
- return new Person(42);
- }
-
- public static int getSuperAge(Super s) {
- return s.getAge();
- }
-
- public static int getPersonAge(Person p) {
- return p.getAge();
- }
-
- public static int makeSuperAge() {
- return createSuper().getAge();
- }
-
- public static int makePersonAge() {
- return createPerson().getAge();
- }
-
- @BeforeClass
- public static void init() {
- // Ensure classes are initialized
- new Person(0).toString();
- }
-
- private StructuredGraph graph;
- private StructuredGraph parsedForCompile;
-
- @Override
- protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) {
- graph = super.parseForCompile(method, compilationId, options);
- parsedForCompile = (StructuredGraph) graph.copy(graph.getDebug());
- return graph;
- }
-
- @Override
- protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
- Registration r = new Registration(invocationPlugins, Super.class);
-
- r.register1("getAge", Receiver.class, new InvocationPlugin() {
- @Override
- public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
- ConstantNode res = b.add(ConstantNode.forInt(new Super().getAge()));
- b.add(new OpaqueNode(res));
- b.push(JavaKind.Int, res);
- return true;
- }
- });
- super.registerInvocationPlugins(invocationPlugins);
- }
-
- public static int referenceMakeSuperAge() {
- return 11;
- }
-
- public static int referenceMakePersonAge() {
- return 42;
- }
-
- @Test
- public void test01() {
- Super inheritsHC = new Super();
- Person overridesHC = new Person(0);
-
- // Ensure the profile for getSuperAge includes both receiver types
- getSuperAge(inheritsHC);
- getSuperAge(overridesHC);
-
- test("getSuperAge", inheritsHC);
- test("getSuperAge", overridesHC);
-
- // Check that the virtual dispatch test exists after bytecode parsing
- Assert.assertEquals(1, parsedForCompile.getNodes().filter(LoadMethodNode.class).count());
- Assert.assertEquals(1, parsedForCompile.getNodes().filter(LoadHubNode.class).count());
-
- // Check for the marker node indicating the intrinsic was applied
- Assert.assertEquals(1, parsedForCompile.getNodes().filter(OpaqueNode.class).count());
-
- // Final graph should have a single invoke
- List<Node> invokes = graph.getNodes().filter(n -> n instanceof Invoke).snapshot();
- Assert.assertEquals(invokes.toString(), 1, invokes.size());
- }
-
- @Test
- public void test02() {
- test("getPersonAge", new Person(0));
-
- // Check that the virtual dispatch test does not exist after bytecode parsing
- Assert.assertEquals(0, parsedForCompile.getNodes().filter(LoadMethodNode.class).count());
- Assert.assertEquals(0, parsedForCompile.getNodes().filter(LoadHubNode.class).count());
-
- Assert.assertEquals(0, parsedForCompile.getNodes().filter(InvokeNode.class).count());
- }
-
- @Test
- public void test03() {
- test("makeSuperAge");
-
- // Check that the virtual dispatch test does not exist after bytecode parsing
- Assert.assertEquals(0, parsedForCompile.getNodes().filter(LoadMethodNode.class).count());
- Assert.assertEquals(0, parsedForCompile.getNodes().filter(LoadHubNode.class).count());
-
- StructuredGraph referenceGraph = parseEager("referenceMakeSuperAge", AllowAssumptions.NO);
- assertEquals(referenceGraph, graph, true, true);
- }
-
- @Test
- public void test04() {
- test("makePersonAge");
-
- // Check that the virtual dispatch test exists after bytecode parsing
- Assert.assertEquals(1, parsedForCompile.getNodes().filter(LoadMethodNode.class).count());
- Assert.assertEquals(1, parsedForCompile.getNodes().filter(LoadHubNode.class).count());
-
- StructuredGraph referenceGraph = parseEager("referenceMakePersonAge", AllowAssumptions.NO);
- assertEquals(referenceGraph, graph, true, true);
- }
-
- static final class ReadCacheEntry {
-
- public final Object identity;
- public final ValueNode object;
-
- ReadCacheEntry(Object identity, ValueNode object) {
- this.identity = identity;
- this.object = object;
- }
-
- @Override
- public int hashCode() {
- int result = ((identity == null) ? 0 : identity.hashCode());
- return result + System.identityHashCode(object);
- }
- }
-
- public static int getHashCode(ReadCacheEntry obj) {
- return obj.hashCode();
- }
-
- @Test
- public void test05() {
- ReadCacheEntry val1 = new ReadCacheEntry("identity", ConstantNode.forBoolean(false));
- ReadCacheEntry val2 = new ReadCacheEntry(Integer.valueOf(34), ConstantNode.forInt(42));
- for (int i = 0; i < 10000; i++) {
- getHashCode(val2);
- }
- test("getHashCode", val1);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,22 +24,14 @@
package org.graalvm.compiler.core.test;
-import java.util.HashMap;
-import java.util.List;
-
import org.graalvm.compiler.core.phases.HighTier;
import org.graalvm.compiler.core.phases.MidTier;
import org.graalvm.compiler.nodes.InvokeNode;
-import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.extended.LoadHubNode;
-import org.graalvm.compiler.nodes.extended.LoadMethodNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.compiler.test.SubprocessUtil;
import org.junit.Assert;
-import org.junit.Assume;
import org.junit.Test;
public class HashCodeTest extends GraalCompilerTest {
@@ -81,10 +73,6 @@
return System.identityHashCode(NonOverridingConstant);
}
- public static final int hashCodeNoFoldOverridingSnippet01(Object o) {
- return o.hashCode();
- }
-
public static final int identityHashCodeFoldOverridingSnippet01() {
return System.identityHashCode(OverridingConstant);
}
@@ -117,56 +105,17 @@
@Test
public void test05() {
- checkForGuardedIntrinsicPattern("hashCodeNoFoldOverridingSnippet01");
-
- Object nullObject = null;
- test("hashCodeNoFoldOverridingSnippet01", nullObject);
- test("hashCodeNoFoldOverridingSnippet01", new Object());
- test("hashCodeNoFoldOverridingSnippet01", new DontOverrideHashCode());
- }
-
- @Test
- public void test06() {
StructuredGraph g = buildGraphAfterMidTier("identityHashCodeFoldOverridingSnippet01");
Assert.assertEquals(0, g.getNodes().filter(InvokeNode.class).count());
}
@Test
- public void test07() {
+ public void test06() {
initialize(DontOverrideHashCode.class);
StructuredGraph g = buildGraphAfterMidTier("dontOverrideHashCodeFinalClass");
Assert.assertEquals(0, g.getNodes().filter(InvokeNode.class).count());
}
- public static final int hashCodeInterface(Appendable o) {
- return o.hashCode();
- }
-
- @Test
- public void test08() {
- // This test requires profiling information which does not work reliable across platforms
- // when running with -Xcomp
- List<String> commandLine = SubprocessUtil.getVMCommandLine();
- Assume.assumeTrue(commandLine != null);
- Assume.assumeFalse(commandLine.contains("-Xcomp"));
- initialize(Appendable.class);
- checkForGuardedIntrinsicPattern("hashCodeInterface");
-
- // Ensure the profile for the dispatch in hashCodeSnippet01
- // has a receiver type that does not select Object.hashCode intrinsic
- hashCodeSnippet01(new HashMap<>());
- checkForGuardedIntrinsicPattern("hashCodeSnippet01");
- }
-
- private void checkForGuardedIntrinsicPattern(String name) {
- StructuredGraph g = parseForCompile(getResolvedJavaMethod(name));
- int invokeNodeCount = g.getNodes().filter(InvokeNode.class).count();
- int invokeWithExceptionNodeCount = g.getNodes().filter(InvokeWithExceptionNode.class).count();
- Assert.assertEquals(1, invokeNodeCount + invokeWithExceptionNodeCount);
- Assert.assertEquals(1, g.getNodes().filter(LoadHubNode.class).count());
- Assert.assertEquals(1, g.getNodes().filter(LoadMethodNode.class).count());
- }
-
@SuppressWarnings("try")
private StructuredGraph buildGraphAfterMidTier(String name) {
StructuredGraph g = parseForCompile(getResolvedJavaMethod(name));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,6 +32,7 @@
import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
@@ -39,7 +40,6 @@
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
/**
@@ -226,7 +226,7 @@
private void testCombinedIf(String snippet, int count) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new FloatingReadPhase().apply(graph);
MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
@@ -247,7 +247,7 @@
}
}
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) {
fs.replaceFirstInput(param, null);
param.safeDelete();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,6 +31,7 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
@@ -38,7 +39,6 @@
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@@ -71,7 +71,7 @@
DebugContext debug = getDebugContext();
try (DebugContext.Scope s = debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new FloatingReadPhase().apply(graph);
MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerDivPowerOf2Test.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.core.test;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.calc.RightShiftNode;
+import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
+import org.junit.Test;
+
+public class IntegerDivPowerOf2Test extends GraalCompilerTest {
+
+ public static int positiveDivByPowerOf2(boolean flag) {
+ int val = flag ? 1 : 10;
+ GraalDirectives.blackhole(val);
+ return val / 8;
+ }
+
+ @Test
+ public void testPositiveDivByPowerOf2() {
+ StructuredGraph graph = parseForCompile(getResolvedJavaMethod("positiveDivByPowerOf2"));
+ // We expect no rounding is needed
+ assertTrue(countShiftNode(graph) == 1);
+ }
+
+ private static int countShiftNode(StructuredGraph graph) {
+ return graph.getNodes().filter(node -> node instanceof RightShiftNode || node instanceof UnsignedRightShiftNode).count();
+ }
+
+ public static int unknownDivByPowerOf2(boolean flag) {
+ int val = flag ? 0x800000F0 : 0x20;
+ GraalDirectives.blackhole(val);
+ return val / 8;
+ }
+
+ @Test
+ public void testUnknownDivByPowerOf2() {
+ StructuredGraph graph = parseForCompile(getResolvedJavaMethod("unknownDivByPowerOf2"));
+ // We expect no rounding is needed
+ assertTrue(graph.getNodes().filter(RightShiftNode.class).count() <= 1);
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerEqualsCanonicalizerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerEqualsCanonicalizerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,13 +24,11 @@
package org.graalvm.compiler.core.test;
-import org.junit.Test;
-
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Test;
public class IntegerEqualsCanonicalizerTest extends GraalCompilerTest {
@@ -168,7 +166,7 @@
private StructuredGraph getCanonicalizedGraph(String snippet) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
for (FrameState state : graph.getNodes(FrameState.TYPE).snapshot()) {
state.replaceAtUsages(null);
state.safeDelete();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -36,7 +36,6 @@
import org.graalvm.compiler.phases.common.LockEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Test;
@@ -70,7 +69,7 @@
test("testSynchronizedSnippet", new A(), new A());
StructuredGraph graph = getGraph("testSynchronizedSnippet", false);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
new LockEliminationPhase().apply(graph);
assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count());
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -88,7 +87,7 @@
test("testSynchronizedMethodSnippet", new A());
StructuredGraph graph = getGraph("testSynchronizedMethodSnippet", false);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
new LockEliminationPhase().apply(graph);
assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count());
assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -106,7 +105,7 @@
public void testUnrolledSync() {
StructuredGraph graph = getGraph("testUnrolledSyncSnippet", false);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
- canonicalizer.apply(graph, new PhaseContext(getProviders()));
+ canonicalizer.apply(graph, getProviders());
HighTierContext context = getDefaultHighTierContext();
new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context);
new LockEliminationPhase().apply(graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,8 +31,8 @@
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class LoopFullUnrollTest extends GraalCompilerTest {
@@ -88,7 +88,7 @@
try (DebugContext.Scope s = debug.scope(getClass().getSimpleName(), new DebugDumpScope(snippet))) {
final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context);
assertTrue(graph.getNodes().filter(LoopBeginNode.class).count() == loopCount);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,7 +31,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class LoopUnswitchTest extends GraalCompilerTest {
@@ -134,8 +133,8 @@
graph.clearAllStateAfter();
referenceGraph.clearAllStateAfter();
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
- new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
+ new CanonicalizerPhase().apply(referenceGraph, getProviders());
try (DebugContext.Scope s = debug.scope("Test", new DebugDumpScope("Test:" + snippet))) {
assertEquals(referenceGraph, graph);
} catch (Throwable e) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,7 +32,6 @@
import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class MergeCanonicalizerTest extends GraalCompilerTest {
@@ -71,8 +70,8 @@
private void testReturnCount(String snippet, int returnCount) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
+ new CanonicalizerPhase().apply(graph, getProviders());
graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph");
assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count());
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,12 +33,12 @@
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.CanonicalizerPhase.CustomCanonicalizer;
import org.graalvm.compiler.phases.contract.NodeCostUtil;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -318,12 +318,12 @@
}
}
- private static class GraphCostPhase extends BasePhase<PhaseContext> {
+ private static class GraphCostPhase extends BasePhase<CoreProviders> {
private double finalCycles;
private double finalSize;
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
finalCycles = NodeCostUtil.computeGraphCycles(graph, true);
finalSize = NodeCostUtil.computeGraphSize(graph);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -49,7 +49,7 @@
import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.compiler.test.GraalTest;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
@@ -82,7 +82,7 @@
Classpath() throws IOException {
List<String> names = new ArrayList<>(Arrays.asList(System.getProperty("java.class.path").split(File.pathSeparator)));
- if (GraalTest.Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
names.addAll(Arrays.asList(System.getProperty("sun.boot.class.path").split(File.pathSeparator)));
} else {
names.addAll(Arrays.asList(System.getProperty("jdk.module.path").split(File.pathSeparator)));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,11 +33,11 @@
import org.graalvm.compiler.nodes.calc.IsNullNode;
import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@@ -103,7 +103,7 @@
private StructuredGraph compileTestSnippet(final String snippet) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
canonicalizer.apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,7 +30,6 @@
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class PushThroughIfTest extends GraalCompilerTest {
@@ -66,15 +65,15 @@
fs.replaceAtUsages(null);
GraphUtil.killWithUnusedFloatingInputs(fs);
}
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
+ new CanonicalizerPhase().apply(graph, getProviders());
StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES);
for (FrameState fs : referenceGraph.getNodes(FrameState.TYPE).snapshot()) {
fs.replaceAtUsages(null);
GraphUtil.killWithUnusedFloatingInputs(fs);
}
- new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(referenceGraph, getProviders());
assertEquals(referenceGraph, graph);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,11 +30,11 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.memory.FloatingReadNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.FloatingReadPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -89,7 +89,7 @@
// check shape of graph, with lots of assumptions. will probably fail if graph
// structure changes significantly
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new FloatingReadPhase().apply(graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReassociateAndCanonicalTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReassociateAndCanonicalTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,14 +24,12 @@
package org.graalvm.compiler.core.test;
-import org.junit.Test;
-
import org.graalvm.compiler.graph.IterableNodeType;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Test;
public class ReassociateAndCanonicalTest extends GraalCompilerTest {
@@ -247,9 +245,9 @@
private <T extends Node & IterableNodeType> void test(String test, String ref) {
StructuredGraph testGraph = parseEager(test, AllowAssumptions.NO);
- new CanonicalizerPhase().apply(testGraph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(testGraph, getProviders());
StructuredGraph refGraph = parseEager(ref, AllowAssumptions.NO);
- new CanonicalizerPhase().apply(refGraph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(refGraph, getProviders());
assertEquals(testGraph, refGraph);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -42,7 +42,7 @@
public class ReferenceGetLoopTest extends GraalCompilerTest {
@Override
- protected boolean checkMidTierGraph(StructuredGraph graph) {
+ protected void checkMidTierGraph(StructuredGraph graph) {
final LoopsData loops = new LoopsData(graph);
boolean found = false;
for (LoopEx loop : loops.loops()) {
@@ -62,7 +62,6 @@
if (!found) {
assertTrue(false, "Reference.referent not found in loop: " + getCanonicalGraphString(graph, true, false));
}
- return true;
}
public volatile Object referent;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,8 +27,8 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
/**
@@ -133,7 +133,7 @@
// No debug scope to reduce console noise for @Test(expected = ...) tests
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph");
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new CanonicalizerPhase().apply(graph, context);
StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO);
assertEquals(referenceGraph, graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java Fri Jun 28 14:36:42 2019 +0530
@@ -41,6 +41,7 @@
import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode;
import org.graalvm.compiler.nodes.cfg.Block;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
@@ -50,7 +51,6 @@
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class SchedulingTest2 extends GraphScheduleTest {
@@ -98,7 +98,7 @@
}
}
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context);
MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampCanonicalizerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampCanonicalizerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,14 +24,12 @@
package org.graalvm.compiler.core.test;
-import org.junit.Test;
-
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Test;
/**
* This class tests some specific patterns the stamp system should be able to canonicalize away
@@ -113,7 +111,7 @@
private void testZeroReturn(String methodName) {
StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
new DeadCodeEliminationPhase().apply(graph);
assertConstantReturn(graph, 0);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,7 +28,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class StraighteningTest extends GraalCompilerTest {
@@ -91,7 +90,7 @@
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
DebugContext debug = graph.getDebug();
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
assertEquals(referenceGraph, graph);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -44,7 +44,6 @@
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@@ -188,14 +187,14 @@
* tail-duplication gets activated thus resulting in a graph with more nodes than the
* reference graph.
*/
- new ConditionalEliminationPhase(false).apply(graph, new PhaseContext(getProviders()));
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new ConditionalEliminationPhase(false).apply(graph, getProviders());
+ new CanonicalizerPhase().apply(graph, getProviders());
// a second canonicalizer is needed to process nested MaterializeNodes
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO);
- new ConditionalEliminationPhase(false).apply(referenceGraph, new PhaseContext(getProviders()));
- new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
- new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
+ new ConditionalEliminationPhase(false).apply(referenceGraph, getProviders());
+ new CanonicalizerPhase().apply(referenceGraph, getProviders());
+ new CanonicalizerPhase().apply(referenceGraph, getProviders());
assertEquals(referenceGraph, graph);
}
@@ -245,8 +244,8 @@
private <T extends Node> void testHelper(String snippet, Class<T> clazz) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
+ new CanonicalizerPhase().apply(graph, getProviders());
DebugContext debug = graph.getDebug();
debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph " + snippet);
Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,11 +30,11 @@
import org.graalvm.compiler.nodes.extended.UnsafeAccessNode;
import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.WriteNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Assert;
@@ -118,7 +118,7 @@
}
public void testEarlyReadElimination(StructuredGraph graph, int reads, int writes) {
- PhaseContext context = getDefaultHighTierContext();
+ CoreProviders context = getDefaultHighTierContext();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
canonicalizer.apply(graph, context);
new EarlyReadEliminationPhase(canonicalizer).apply(graph, context);
@@ -133,7 +133,7 @@
public void testPartialEscapeReadElimination(StructuredGraph graph, int reads, int writes) {
OptionValues options = graph.getOptions();
- PhaseContext context = getDefaultHighTierContext();
+ CoreProviders context = getDefaultHighTierContext();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
canonicalizer.apply(graph, context);
new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,9 +28,9 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Test;
@@ -146,7 +146,7 @@
ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
OptionValues options = graph.getOptions();
- PhaseContext context = getDefaultHighTierContext();
+ CoreProviders context = getDefaultHighTierContext();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
if (canonicalizeBefore) {
canonicalizer.apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,7 +31,6 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class UnusedArray extends GraalCompilerTest {
@@ -67,7 +66,7 @@
public void test(String method) {
StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.YES);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
NodeIterable<NewArrayNode> newArrayNodes = graph.getNodes().filter(NewArrayNode.class);
assertThat(newArrayNodes, isEmpty());
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsage.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,14 +29,14 @@
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
-public class VerifyBailoutUsage extends VerifyPhase<PhaseContext> {
+public class VerifyBailoutUsage extends VerifyPhase<CoreProviders> {
private static final String[] AllowedPackagePrefixes;
@@ -73,7 +73,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
final ResolvedJavaType bailoutType = context.getMetaAccess().lookupJavaType(BailoutException.class);
ResolvedJavaMethod caller = graph.method();
String holderQualified = caller.format("%H");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBufferUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.core.test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.graalvm.compiler.core.common.type.ObjectStamp;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
+import org.graalvm.compiler.phases.VerifyPhase;
+import org.graalvm.compiler.serviceprovider.BufferUtil;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * See {@link BufferUtil}.
+ */
+public class VerifyBufferUsage extends VerifyPhase<CoreProviders> {
+
+ private final Set<String> bufferTypes = new HashSet<>(Arrays.asList(
+ "Ljava/nio/Buffer;",
+ "Ljava/nio/ByteBuffer;",
+ "Ljava/nio/ShortBuffer;",
+ "Ljava/nio/CharBuffer;",
+ "Ljava/nio/IntBuffer;",
+ "Ljava/nio/LongBuffer;",
+ "Ljava/nio/FloatBuffer;",
+ "Ljava/nio/DoubleBuffer;",
+ "Ljava/nio/MappedByteBuffer;"));
+
+ private final Set<String> bufferMethods = new HashSet<>(Arrays.asList(
+ "position",
+ "limit",
+ "mark",
+ "reset",
+ "clear",
+ "flip",
+ "rewind"));
+
+ @Override
+ protected void verify(StructuredGraph graph, CoreProviders context) {
+ ResolvedJavaMethod caller = graph.method();
+ for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
+ ResolvedJavaMethod callee = t.targetMethod();
+ String calleeClassName = callee.getDeclaringClass().getName();
+ String calleeName = callee.getName();
+ if (bufferTypes.contains(calleeClassName) &&
+ bufferMethods.contains(calleeName) &&
+ !callee.getSignature().getReturnKind().isPrimitive()) {
+ StackTraceElement e = caller.asStackTraceElement(t.invoke().bci());
+ ResolvedJavaType receiverType = ((ObjectStamp) t.arguments().get(0).stamp(NodeView.DEFAULT)).type();
+ if (!receiverType.getName().equals("Ljava/nio/Buffer;")) {
+ throw new VerificationError(
+ "%s: Cast receiver of type %s to java.nio.Buffer for call to %s to avoid problems with co-variant overloads added by https://bugs.openjdk.java.net/browse/JDK-4774077",
+ e, receiverType.toJavaName(),
+ callee.format("%H.%n(%p)"));
+ }
+ }
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,15 +24,14 @@
package org.graalvm.compiler.core.test;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
-
import java.lang.annotation.Annotation;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -40,7 +39,7 @@
/**
* Verifies a method is annotated with CallerSensitive iff it calls Reflection#getCallerClass().
*/
-public class VerifyCallerSensitiveMethods extends VerifyPhase<PhaseContext> {
+public class VerifyCallerSensitiveMethods extends VerifyPhase<CoreProviders> {
Class<? extends Annotation> callerSensitiveClass;
Class<?> reflectionClass;
@@ -54,7 +53,7 @@
public VerifyCallerSensitiveMethods() {
try {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
reflectionClass = classLoader.loadClass("sun.reflect.Reflection");
callerSensitiveClass = (Class<? extends Annotation>) classLoader.loadClass("sun.reflect.ConstantPool");
} else {
@@ -67,7 +66,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
Invoke invoke = callsReflectionGetCallerClass(graph, context);
Annotation annotation = graph.method().getAnnotation(callerSensitiveClass);
if (invoke != null) {
@@ -81,7 +80,7 @@
}
}
- private Invoke callsReflectionGetCallerClass(StructuredGraph graph, PhaseContext context) {
+ private Invoke callsReflectionGetCallerClass(StructuredGraph graph, CoreProviders context) {
ResolvedJavaType reflectionType = context.getMetaAccess().lookupJavaType(reflectionClass);
for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
ResolvedJavaMethod callee = t.targetMethod();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -46,8 +46,8 @@
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.nodes.java.StoreIndexedNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -68,7 +68,7 @@
* {@link DebugContext#log(String)} , {@link DebugContext#dump(int, Object, String)},
* {@link DebugContext#logAndIndent(String)} and {@link DebugContext#verify(Object, String)}.
*/
-public class VerifyDebugUsage extends VerifyPhase<PhaseContext> {
+public class VerifyDebugUsage extends VerifyPhase<CoreProviders> {
@Override
public boolean checkContract() {
@@ -78,7 +78,7 @@
MetaAccessProvider metaAccess;
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
metaAccess = context.getMetaAccess();
ResolvedJavaType debugType = metaAccess.lookupJavaType(DebugContext.class);
ResolvedJavaType nodeType = metaAccess.lookupJavaType(Node.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyFoldableMethods.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyFoldableMethods.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,8 +32,8 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -41,7 +41,7 @@
/**
* Verifies that all {@link Fold} annotated methods have at least one caller.
*/
-public class VerifyFoldableMethods extends VerifyPhase<PhaseContext> {
+public class VerifyFoldableMethods extends VerifyPhase<CoreProviders> {
@Override
public boolean checkContract() {
@@ -52,7 +52,7 @@
ResolvedJavaType generatedInvocationPluginType;
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
ResolvedJavaMethod method = graph.method();
if (method.getAnnotation(Fold.class) != null) {
foldables.putIfAbsent(method, false);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGetOptionsUsage.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGetOptionsUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,8 +31,8 @@
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -45,7 +45,7 @@
* general but since there are several canonical methods with varying signatures this covers more
* cases.
*/
-public class VerifyGetOptionsUsage extends VerifyPhase<PhaseContext> {
+public class VerifyGetOptionsUsage extends VerifyPhase<CoreProviders> {
static Method lookupMethod(Class<?> klass, String name) {
for (Method m : klass.getDeclaredMethods()) {
if (m.getName().equals(name)) {
@@ -56,7 +56,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
MetaAccessProvider metaAccess = context.getMetaAccess();
ResolvedJavaType canonicalizerToolClass = metaAccess.lookupJavaType(CanonicalizerTool.class);
boolean hasTool = false;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGraphAddUsage.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyGraphAddUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -41,14 +41,14 @@
import org.graalvm.compiler.nodes.ValueProxyNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.java.NewInstanceNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
-public class VerifyGraphAddUsage extends VerifyPhase<PhaseContext> {
+public class VerifyGraphAddUsage extends VerifyPhase<CoreProviders> {
private static final Method ADD_OR_UNIQUE;
private static final Method CONSTRUCTOR_NEW_INSTANCE;
private static final EconomicSet<Class<?>> ALLOWED_CLASSES = EconomicSet.create();
@@ -66,7 +66,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
boolean allowed = false;
for (Class<?> cls : ALLOWED_CLASSES) {
ResolvedJavaType declaringClass = graph.method().getDeclaringClass();
@@ -87,7 +87,7 @@
}
}
- private void checkNonFactory(StructuredGraph graph, EconomicSet<Node> seen, PhaseContext context, ValueNode node) {
+ private void checkNonFactory(StructuredGraph graph, EconomicSet<Node> seen, CoreProviders context, ValueNode node) {
if (seen.contains(node)) {
return;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyInstanceOfUsage.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyInstanceOfUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,8 +29,8 @@
import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.InstanceOfNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -39,7 +39,7 @@
/**
* Checks that we do not use {@code instanceof} for types where faster alternatives are available.
*/
-public class VerifyInstanceOfUsage extends VerifyPhase<PhaseContext> {
+public class VerifyInstanceOfUsage extends VerifyPhase<CoreProviders> {
private static final Class<?>[] FORBIDDEN_INSTANCE_OF_CHECKS = {
MoveOp.class,
@@ -53,7 +53,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
final ResolvedJavaType[] bailoutType = new ResolvedJavaType[FORBIDDEN_INSTANCE_OF_CHECKS.length];
for (int i = 0; i < FORBIDDEN_INSTANCE_OF_CHECKS.length; i++) {
bailoutType[i] = context.getMetaAccess().lookupJavaType(FORBIDDEN_INSTANCE_OF_CHECKS[i]);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifySystemPropertyUsage.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifySystemPropertyUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,8 +29,8 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -43,7 +43,7 @@
* can be modified by application code so {@link Services#getSavedProperties()} should be used
* instead.
*/
-public class VerifySystemPropertyUsage extends VerifyPhase<PhaseContext> {
+public class VerifySystemPropertyUsage extends VerifyPhase<CoreProviders> {
static final Class<?>[] BOXES = {Integer.class, Long.class, Boolean.class, Float.class, Double.class};
static final int JVMCI_VERSION_MAJOR;
@@ -65,7 +65,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
MetaAccessProvider metaAccess = context.getMetaAccess();
final ResolvedJavaType systemType = metaAccess.lookupJavaType(System.class);
final ResolvedJavaType[] boxTypes = new ResolvedJavaType[BOXES.length];
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUnsafeAccess.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUnsafeAccess.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,8 +33,8 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.java.InstanceOfNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -46,10 +46,10 @@
* Checks that the {@link Unsafe} singleton instance is only accessed via well known classes such as
* {@link GraalUnsafeAccess}.
*/
-public class VerifyUnsafeAccess extends VerifyPhase<PhaseContext> {
+public class VerifyUnsafeAccess extends VerifyPhase<CoreProviders> {
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
MetaAccessProvider metaAccess = context.getMetaAccess();
final ResolvedJavaType unsafeType = metaAccess.lookupJavaType(Unsafe.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUpdateUsages.java Fri Jun 28 14:36:42 2019 +0530
@@ -34,8 +34,8 @@
import org.graalvm.compiler.nodes.java.LoadFieldNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.java.StoreFieldNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -45,7 +45,7 @@
* Try to ensure that methods which update {@link Input} or {@link OptionalInput} fields also
* include a call to {@link Node#updateUsages} or {@link Node#updateUsagesInterface}.
*/
-public class VerifyUpdateUsages extends VerifyPhase<PhaseContext> {
+public class VerifyUpdateUsages extends VerifyPhase<CoreProviders> {
@Override
public boolean checkContract() {
@@ -56,7 +56,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
if (graph.method().isConstructor()) {
return;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUsageWithEquals.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyUsageWithEquals.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,10 +32,10 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
import org.graalvm.compiler.nodes.java.LoadFieldNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.JavaField;
import jdk.vm.ci.meta.JavaKind;
@@ -51,7 +51,7 @@
* checks the correct usage of the given type. Equality checks with == or != (except null checks)
* results in an {@link AssertionError}.
*/
-public class VerifyUsageWithEquals extends VerifyPhase<PhaseContext> {
+public class VerifyUsageWithEquals extends VerifyPhase<CoreProviders> {
@Override
public boolean checkContract() {
@@ -143,7 +143,7 @@
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
// bail out if we compare an object of type klass with == or != (except null checks)
ResolvedJavaMethod method = graph.method();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableUsage.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableUsage.java Fri Jun 28 14:36:42 2019 +0530
@@ -34,9 +34,9 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -46,14 +46,14 @@
* Implementors of {@link Virtualizable#virtualize(org.graalvm.compiler.nodes.spi.VirtualizerTool)}
* must not apply effects on their {@link Graph graph} that cannot be easily undone.
*/
-public class VerifyVirtualizableUsage extends VerifyPhase<PhaseContext> {
+public class VerifyVirtualizableUsage extends VerifyPhase<CoreProviders> {
@Override
public boolean checkContract() {
return false;
}
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
final ResolvedJavaType graphType = context.getMetaAccess().lookupJavaType(Graph.class);
final ResolvedJavaType virtualizableType = context.getMetaAccess().lookupJavaType(Virtualizable.class);
final ResolvedJavaType constantNodeType = context.getMetaAccess().lookupJavaType(ConstantNode.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/CompiledMethodTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,7 +31,6 @@
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -63,7 +62,7 @@
public void test1() {
final ResolvedJavaMethod javaMethod = getResolvedJavaMethod("testMethod");
final StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.NO);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
new DeadCodeEliminationPhase().apply(graph);
for (ConstantNode node : ConstantNode.getConstantNodes(graph)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,12 +24,12 @@
package org.graalvm.compiler.core.test.deopt;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.core.test.ea.EATestBase.TestClassObject;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.junit.Assume;
import org.junit.Test;
-import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.core.test.ea.EATestBase.TestClassObject;
-
/**
* In the following tests, we try to deoptimize out of synchronized methods.
*/
@@ -48,7 +48,7 @@
@Test
public void test1() {
// https://bugs.openjdk.java.net/browse/JDK-8182755
- Assume.assumeTrue(Java8OrEarlier);
+ Assume.assumeTrue(JavaVersionUtil.JAVA_SPEC <= 8);
test("testMethodSynchronized", "test");
test("testMethodSynchronized", (Object) null);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,11 +33,11 @@
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.java.AbstractNewObjectNode;
import org.graalvm.compiler.nodes.java.NewInstanceNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
/**
@@ -67,7 +67,7 @@
StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
HighTierContext highTierContext = getDefaultHighTierContext();
createInliningPhase().apply(graph, highTierContext);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
// remove framestates in order to trigger the simplification.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,6 +35,7 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.OptimisticOptimizations;
@@ -43,10 +44,8 @@
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
-
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
@@ -124,7 +123,7 @@
}
}
- private long runAndTimePhase(StructuredGraph g, BasePhase<? super PhaseContext> phase) {
+ private long runAndTimePhase(StructuredGraph g, BasePhase<? super CoreProviders> phase) {
HighTierContext context = getDefaultHighTierContext();
long start = System.currentTimeMillis();
phase.apply(g, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Fri Jun 28 14:36:42 2019 +0530
@@ -166,10 +166,11 @@
/**
* Creates the {@link DebugContext} to use when retrying a compilation.
*
+ * @param initialDebug the debug context used in the failing compilation
* @param options the options for configuring the debug context
* @param logStream the log stream to use in the debug context
*/
- protected abstract DebugContext createRetryDebugContext(OptionValues options, PrintStream logStream);
+ protected abstract DebugContext createRetryDebugContext(DebugContext initialDebug, OptionValues options, PrintStream logStream);
@SuppressWarnings("try")
public final T run(DebugContext initialDebug) {
@@ -277,7 +278,7 @@
ByteArrayOutputStream logBaos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(logBaos);
- try (DebugContext retryDebug = createRetryDebugContext(retryOptions, ps)) {
+ try (DebugContext retryDebug = createRetryDebugContext(initialDebug, retryOptions, ps)) {
T res = performCompilation(retryDebug);
ps.println("There was no exception during retry.");
maybeExitVM(action);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,6 +28,7 @@
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionStability;
import org.graalvm.compiler.options.OptionType;
/**
@@ -36,7 +37,7 @@
public class GraalCompilerOptions {
// @formatter:off
- @Option(help = "Print an informational line to the console for each completed compilation.", type = OptionType.Debug)
+ @Option(help = "Print an informational line to the console for each completed compilation.", type = OptionType.Debug, stability = OptionStability.STABLE)
public static final OptionKey<Boolean> PrintCompilation = new OptionKey<>(false);
@Option(help = "Pattern for method(s) that will trigger an exception when compiled. " +
"This option exists to test handling compilation crashes gracefully. " +
@@ -44,9 +45,9 @@
"suffix will raise a bailout exception and a ':PermanentBailout' " +
"suffix will raise a permanent bailout exception.", type = OptionType.Debug)
public static final OptionKey<String> CrashAt = new OptionKey<>(null);
- @Option(help = "Treat compilation bailouts like compilation failures.", type = OptionType.User)
+ @Option(help = "Treat compilation bailouts like compilation failures.", type = OptionType.User, stability = OptionStability.STABLE)
public static final OptionKey<Boolean> CompilationBailoutAsFailure = new OptionKey<>(false);
- @Option(help = "file:doc-files/CompilationFailureActionHelp.txt", type = OptionType.User)
+ @Option(help = "file:doc-files/CompilationFailureActionHelp.txt", type = OptionType.User, stability = OptionStability.STABLE)
public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Silent);
@Option(help = "The maximum number of compilation failures to handle with the action specified " +
"by CompilationFailureAction before changing to a less verbose action. " +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalServiceThread.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.core;
+
+/**
+ * This is a utility class for Threads started by the compiler itself. In certain execution
+ * environments extra work must be done for these threads to execute correctly and this class
+ * provides hooks for this work.
+ */
+public class GraalServiceThread extends Thread {
+ private final Runnable runnable;
+
+ public GraalServiceThread(Runnable runnable) {
+ super();
+ this.runnable = runnable;
+ }
+
+ @Override
+ public final void run() {
+ beforeRun();
+ try {
+ runnable.run();
+ } finally {
+ afterRun();
+ }
+ }
+
+ /**
+ * Substituted by {@code com.oracle.svm.graal.hotspot.libgraal.
+ * Target_org_graalvm_compiler_truffle_common_TruffleCompilerRuntimeInstance} to attach to the
+ * peer runtime if required.
+ */
+ private void afterRun() {
+ }
+
+ /**
+ * Substituted by {@code com.oracle.svm.graal.hotspot.libgraal.
+ * Target_org_graalvm_compiler_truffle_common_TruffleCompilerRuntimeInstance} to attach to the
+ * peer runtime if required.
+ */
+ private void beforeRun() {
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java Fri Jun 28 14:36:42 2019 +0530
@@ -124,7 +124,11 @@
}
@SuppressWarnings("try")
- private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites,
+ private static LIRGenerationResult emitLIR0(Backend backend,
+ StructuredGraph graph,
+ Object stub,
+ RegisterConfig registerConfig,
+ LIRSuites lirSuites,
String[] allocationRestrictedTo) {
DebugContext debug = graph.getDebug();
try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -44,7 +44,10 @@
public interface LIRGenerationProvider {
LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes);
- LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph,
+ LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId,
+ LIR lir,
+ RegisterConfig registerConfig,
+ StructuredGraph graph,
Object stub);
NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
@@ -52,7 +55,9 @@
/**
* Creates the object used to fill in the details of a given compilation result.
*/
- CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
+ CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult,
+ FrameMap frameMap,
+ CompilationResult compilationResult,
CompilationResultBuilderFactory factory);
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java Fri Jun 28 14:36:42 2019 +0530
@@ -47,6 +47,6 @@
appendPhase(new ExpandLogicPhase());
- appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.FINAL_SCHEDULE));
+ appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,6 +35,7 @@
import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.RemoveValueProxyPhase;
+import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase;
import org.graalvm.compiler.phases.tiers.MidTierContext;
public class EconomyMidTier extends PhaseSuite<MidTierContext> {
@@ -53,5 +54,7 @@
appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER));
appendPhase(new FrameStateAssignmentPhase());
+
+ appendPhase(new WriteBarrierAdditionPhase());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,10 +32,10 @@
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.LogicConstantNode;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
/**
* A utility phase for detecting when a phase would change the graph and reporting extra information
@@ -46,7 +46,7 @@
*
* @param <C>
*/
-public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSuite<C> {
+public class GraphChangeMonitoringPhase<C extends CoreProviders> extends PhaseSuite<C> {
private final String message;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,7 +25,6 @@
package org.graalvm.compiler.core.phases;
import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination;
-import static org.graalvm.compiler.core.common.GraalOptions.FullUnroll;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.core.common.GraalOptions.LoopPeeling;
import static org.graalvm.compiler.core.common.GraalOptions.LoopUnswitch;
@@ -100,21 +99,17 @@
}
LoopPolicies loopPolicies = createLoopPolicies();
- if (FullUnroll.getValue(options)) {
- appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies));
- }
+ appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies));
if (OptLoopTransform.getValue(options)) {
if (LoopPeeling.getValue(options)) {
- appendPhase(new LoopPeelingPhase(loopPolicies));
+ appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopPeelingPhase(loopPolicies)));
}
if (LoopUnswitch.getValue(options)) {
- appendPhase(new LoopUnswitchingPhase(loopPolicies));
+ appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopUnswitchingPhase(loopPolicies)));
}
}
- appendPhase(canonicalizer);
-
if (PartialEscapeAnalysis.getValue(options)) {
appendPhase(new PartialEscapePhase(true, canonicalizer, options));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java Fri Jun 28 14:36:42 2019 +0530
@@ -77,7 +77,8 @@
appendPhase(new ExpandLogicPhase());
- appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS)));
+ appendPhase(new FixReadsPhase(true,
+ new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS_IMPLICIT_NULL_CHECKS)));
appendPhase(canonicalizerWithoutGVN);
@@ -87,6 +88,6 @@
appendPhase(new PropagateDeoptimizeProbabilityPhase());
- appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.FINAL_SCHEDULE));
+ appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,9 +24,6 @@
package org.graalvm.compiler.core.phases;
-import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.GuardTargets;
-import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.NonDeoptGuardTargets;
-import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks;
import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.core.common.GraalOptions.OptDeoptimizationGrouping;
@@ -35,6 +32,9 @@
import static org.graalvm.compiler.core.common.GraalOptions.PartialUnroll;
import static org.graalvm.compiler.core.common.GraalOptions.ReassociateInvariants;
import static org.graalvm.compiler.core.common.GraalOptions.VerifyHeapAtReturn;
+import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.GuardTargets;
+import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.NonDeoptGuardTargets;
+import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks;
import org.graalvm.compiler.loop.DefaultLoopPolicies;
import org.graalvm.compiler.loop.LoopPolicies;
@@ -56,6 +56,7 @@
import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.VerifyHeapAtReturnPhase;
+import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase;
import org.graalvm.compiler.phases.tiers.MidTierContext;
public class MidTier extends PhaseSuite<MidTierContext> {
@@ -109,6 +110,8 @@
}
appendPhase(canonicalizer);
+
+ appendPhase(new WriteBarrierAdditionPhase());
}
public LoopPolicies createLoopPolicies() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,11 +28,14 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionStability;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.GraalServices;
@@ -92,12 +95,12 @@
@Option(help = "Pattern for specifying scopes in which logging is enabled. " +
"See the Dump option for the pattern syntax.", type = OptionType.Debug)
public static final OptionKey<String> Verify = new OptionKey<>(null);
- @Option(help = "file:doc-files/DumpHelp.txt", type = OptionType.Debug)
+ @Option(help = "file:doc-files/DumpHelp.txt", type = OptionType.Debug, stability = OptionStability.STABLE)
public static final OptionKey<String> Dump = new OptionKey<>(null);
@Option(help = "Pattern for specifying scopes in which logging is enabled. " +
"See the Dump option for the pattern syntax.", type = OptionType.Debug)
public static final OptionKey<String> Log = new OptionKey<>(null);
- @Option(help = "file:doc-files/MethodFilterHelp.txt")
+ @Option(help = "file:doc-files/MethodFilterHelp.txt", stability = OptionStability.STABLE)
public static final OptionKey<String> MethodFilter = new OptionKey<>(null);
@Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug)
public static final OptionKey<Boolean> MethodFilterRootOnly = new OptionKey<>(false);
@@ -119,7 +122,7 @@
public static final OptionKey<String> MetricsThreadFilter = new OptionKey<>(null);
@Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug)
public static final OptionKey<Boolean> DebugStubsAndSnippets = new OptionKey<>(false);
- @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug)
+ @Option(help = "Send compiler IR to dump handlers on error.", type = OptionType.Debug)
public static final OptionKey<Boolean> DumpOnError = new OptionKey<>(false);
@Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
public static final OptionKey<Boolean> InterceptBailout = new OptionKey<>(false);
@@ -203,7 +206,9 @@
if (DumpPath.hasBeenSet(options)) {
dumpDir = Paths.get(DumpPath.getValue(options));
} else {
- dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(GraalServices.getGlobalTimeStamp()));
+ Date date = new Date(GraalServices.getGlobalTimeStamp());
+ SimpleDateFormat formatter = new SimpleDateFormat( "YYYY.MM.dd.HH.mm.ss.SSS" );
+ dumpDir = Paths.get(DumpPath.getValue(options), formatter.format(date));
}
dumpDir = dumpDir.toAbsolutePath();
if (!Files.exists(dumpDir)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java Fri Jun 28 14:36:42 2019 +0530
@@ -118,6 +118,7 @@
/**
* The {@link PrintStream} to which all non-suppressed output from {@link TTY} is written.
+ * Substituted by {@code com.oracle.svm.graal.Target_org_graalvm_compiler_debug_TTY}.
*/
public static final PrintStream out;
static {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Fri Jun 28 14:36:42 2019 +0530
@@ -642,30 +642,6 @@
}
@Override
- public void nodeAdded(Node node) {
- head.event(NodeEvent.NODE_ADDED, node);
- next.event(NodeEvent.NODE_ADDED, node);
- }
-
- @Override
- public void inputChanged(Node node) {
- head.event(NodeEvent.INPUT_CHANGED, node);
- next.event(NodeEvent.INPUT_CHANGED, node);
- }
-
- @Override
- public void usagesDroppedToZero(Node node) {
- head.event(NodeEvent.ZERO_USAGES, node);
- next.event(NodeEvent.ZERO_USAGES, node);
- }
-
- @Override
- public void nodeRemoved(Node node) {
- head.event(NodeEvent.NODE_REMOVED, node);
- next.event(NodeEvent.NODE_REMOVED, node);
- }
-
- @Override
public void changed(NodeEvent e, Node node) {
head.event(e, node);
next.event(e, node);
@@ -1151,7 +1127,7 @@
nodesDeletedSinceLastCompression++;
if (nodeEventListener != null) {
- nodeEventListener.event(NodeEvent.NODE_ADDED, node);
+ nodeEventListener.event(NodeEvent.NODE_REMOVED, node);
}
// nodes aren't removed from the type cache here - they will be removed during iteration
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Fri Jun 28 14:36:42 2019 +0530
@@ -613,6 +613,7 @@
assert assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s, this=%s", newSuccessor, newSuccessor.predecessor, this);
newSuccessor.predecessor = this;
}
+ maybeNotifyInputChanged(this);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,7 +31,6 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.aarch64.AArch64AddressLoweringByUse;
import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
@@ -44,6 +43,7 @@
import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotConstantFieldProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotGCProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
@@ -64,7 +64,6 @@
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins;
-import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
import org.graalvm.compiler.word.WordTypes;
@@ -83,7 +82,7 @@
import jdk.vm.ci.runtime.JVMCIBackend;
@ServiceProvider(HotSpotBackendFactory.class)
-public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory {
+public class AArch64HotSpotBackendFactory extends HotSpotBackendFactory {
@Override
public String getName() {
@@ -112,6 +111,8 @@
HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection();
HotSpotConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess);
HotSpotLoweringProvider lowerer;
+ HotSpotStampProvider stampProvider;
+ HotSpotGCProvider gc;
HotSpotSnippetReflectionProvider snippetReflection;
HotSpotReplacementsImpl replacements;
HotSpotSuitesProvider suites;
@@ -126,7 +127,7 @@
nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(config, codeCache.getRegisterConfig());
}
try (InitTimer rt = timer("create WordTypes")) {
- wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind);
+ wordTypes = createWordTypes(metaAccess, target);
}
try (InitTimer rt = timer("create ForeignCalls provider")) {
foreignCalls = createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
@@ -134,17 +135,23 @@
try (InitTimer rt = timer("create Lowerer provider")) {
lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, target);
}
- HotSpotStampProvider stampProvider = new HotSpotStampProvider();
- Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider);
+ try (InitTimer rt = timer("create stamp provider")) {
+ stampProvider = createStampProvider();
+ }
+ try (InitTimer rt = timer("create GC provider")) {
+ gc = createGCProvider(config);
+ }
+
+ Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, gc);
try (InitTimer rt = timer("create SnippetReflection provider")) {
snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes);
}
try (InitTimer rt = timer("create Bytecode provider")) {
- bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
+ bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection);
}
try (InitTimer rt = timer("create Replacements provider")) {
- replacements = createReplacements(p, snippetReflection, bytecodeProvider);
+ replacements = createReplacements(target, p, snippetReflection, bytecodeProvider);
}
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, graalRuntime.getOptions());
@@ -154,8 +161,7 @@
suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, replacements);
}
providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
- snippetReflection, wordTypes,
- plugins);
+ snippetReflection, wordTypes, plugins, gc);
replacements.setProviders(providers);
}
try (InitTimer rt = timer("instantiate backend")) {
@@ -180,10 +186,6 @@
return new HotSpotRegisters(AArch64HotSpotRegisterConfig.threadRegister, AArch64HotSpotRegisterConfig.heapBaseRegister, sp);
}
- protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
- return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget());
- }
-
protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess,
HotSpotCodeCacheProvider codeCache, WordTypes wordTypes, Value[] nativeABICallerSaveRegisters) {
return new AArch64HotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
@@ -196,10 +198,6 @@
return new AddressLoweringHotSpotSuitesProvider(suitesCreator, config, runtime, addressLoweringPhase);
}
- protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) {
- return new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes);
- }
-
protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls,
HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
return new AArch64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, target);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Fri Jun 28 14:36:42 2019 +0530
@@ -71,7 +71,7 @@
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
leaveFrame(crb, masm, /* emitSafepoint */false, false);
- if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
+ if (JavaVersionUtil.JAVA_SPEC < 8) {
// Restore sp from fp if the exception PC is a method handle call site.
try (ScratchRegister sc = masm.getScratchRegister()) {
Register scratch = sc.getRegister();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayIndexOfStub.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayIndexOfStub.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,7 +24,6 @@
package org.graalvm.compiler.hotspot.amd64;
-import jdk.vm.ci.meta.JavaKind;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
@@ -32,7 +31,6 @@
import org.graalvm.compiler.hotspot.stubs.SnippetStub;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.amd64.AMD64ArrayIndexOfNode;
-import jdk.internal.vm.compiler.word.Pointer;
public class AMD64ArrayIndexOfStub extends SnippetStub {
@@ -41,52 +39,77 @@
}
@Snippet
- private static int indexOfTwoConsecutiveBytes(Pointer arrayPointer, int arrayLength, int searchValue) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, true, arrayPointer, arrayLength, searchValue);
+ private static int indexOfTwoConsecutiveBytes(byte[] array, int arrayLength, int fromIndex, int searchValue) {
+ return AMD64ArrayIndexOfNode.indexOf2ConsecutiveBytes(array, arrayLength, fromIndex, searchValue);
}
@Snippet
- private static int indexOfTwoConsecutiveChars(Pointer arrayPointer, int arrayLength, int searchValue) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, true, arrayPointer, arrayLength, searchValue);
+ private static int indexOfTwoConsecutiveChars(char[] array, int arrayLength, int fromIndex, int searchValue) {
+ return AMD64ArrayIndexOfNode.indexOf2ConsecutiveChars(array, arrayLength, fromIndex, searchValue);
+ }
+
+ @Snippet
+ private static int indexOfTwoConsecutiveCharsCompact(byte[] array, int arrayLength, int fromIndex, int searchValue) {
+ return AMD64ArrayIndexOfNode.indexOf2ConsecutiveChars(array, arrayLength, fromIndex, searchValue);
}
@Snippet
- private static int indexOf1Byte(Pointer arrayPointer, int arrayLength, byte b) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b);
+ private static int indexOf1Byte(byte[] array, int arrayLength, int fromIndex, byte b) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, b);
}
@Snippet
- private static int indexOf2Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b1, b2);
+ private static int indexOf2Bytes(byte[] array, int arrayLength, int fromIndex, byte b1, byte b2) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, b1, b2);
}
@Snippet
- private static int indexOf3Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2, byte b3) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b1, b2, b3);
+ private static int indexOf3Bytes(byte[] array, int arrayLength, int fromIndex, byte b1, byte b2, byte b3) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, b1, b2, b3);
+ }
+
+ @Snippet
+ private static int indexOf4Bytes(byte[] array, int arrayLength, int fromIndex, byte b1, byte b2, byte b3, byte b4) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, b1, b2, b3, b4);
}
@Snippet
- private static int indexOf4Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2, byte b3, byte b4) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Byte, arrayPointer, arrayLength, b1, b2, b3, b4);
+ private static int indexOf1Char(char[] array, int arrayLength, int fromIndex, char c) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c);
}
@Snippet
- private static int indexOf1Char(Pointer arrayPointer, int arrayLength, char c) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c);
+ private static int indexOf2Chars(char[] array, int arrayLength, int fromIndex, char c1, char c2) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c1, c2);
+ }
+
+ @Snippet
+ private static int indexOf3Chars(char[] array, int arrayLength, int fromIndex, char c1, char c2, char c3) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c1, c2, c3);
+ }
+
+ @Snippet
+ private static int indexOf4Chars(char[] array, int arrayLength, int fromIndex, char c1, char c2, char c3, char c4) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c1, c2, c3, c4);
}
@Snippet
- private static int indexOf2Chars(Pointer arrayPointer, int arrayLength, char c1, char c2) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c1, c2);
+ private static int indexOf1CharCompact(byte[] array, int arrayLength, int fromIndex, char c) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c);
+ }
+
+ @Snippet
+ private static int indexOf2CharsCompact(byte[] array, int arrayLength, int fromIndex, char c1, char c2) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c1, c2);
}
@Snippet
- private static int indexOf3Chars(Pointer arrayPointer, int arrayLength, char c1, char c2, char c3) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c1, c2, c3);
+ private static int indexOf3CharsCompact(byte[] array, int arrayLength, int fromIndex, char c1, char c2, char c3) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c1, c2, c3);
}
@Snippet
- private static int indexOf4Chars(Pointer arrayPointer, int arrayLength, char c1, char c2, char c3, char c4) {
- return AMD64ArrayIndexOfNode.optimizedArrayIndexOf(JavaKind.Char, arrayPointer, arrayLength, c1, c2, c3, c4);
+ private static int indexOf4CharsCompact(byte[] array, int arrayLength, int fromIndex, char c1, char c2, char c3, char c4) {
+ return AMD64ArrayIndexOfNode.indexOf(array, arrayLength, fromIndex, c1, c2, c3, c4);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,12 +25,10 @@
package org.graalvm.compiler.hotspot.amd64;
import static jdk.vm.ci.common.InitTimer.timer;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -40,6 +38,7 @@
import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotGCProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
@@ -58,7 +57,7 @@
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins;
-import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
import org.graalvm.compiler.word.WordTypes;
@@ -76,7 +75,7 @@
import jdk.vm.ci.runtime.JVMCIBackend;
@ServiceProvider(HotSpotBackendFactory.class)
-public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
+public class AMD64HotSpotBackendFactory extends HotSpotBackendFactory {
@Override
public String getName() {
@@ -106,6 +105,8 @@
HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection();
ConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess);
HotSpotLoweringProvider lowerer;
+ HotSpotStampProvider stampProvider;
+ HotSpotGCProvider gc;
HotSpotSnippetReflectionProvider snippetReflection;
HotSpotReplacementsImpl replacements;
HotSpotSuitesProvider suites;
@@ -120,7 +121,7 @@
nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(config, codeCache.getRegisterConfig());
}
try (InitTimer rt = timer("create WordTypes")) {
- wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind);
+ wordTypes = createWordTypes(metaAccess, target);
}
try (InitTimer rt = timer("create ForeignCalls provider")) {
foreignCalls = createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
@@ -128,17 +129,23 @@
try (InitTimer rt = timer("create Lowerer provider")) {
lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, target);
}
- HotSpotStampProvider stampProvider = new HotSpotStampProvider();
- Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider);
+ try (InitTimer rt = timer("create stamp provider")) {
+ stampProvider = createStampProvider();
+ }
+ try (InitTimer rt = timer("create GC provider")) {
+ gc = createGCProvider(config);
+ }
+
+ Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, gc);
try (InitTimer rt = timer("create SnippetReflection provider")) {
snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes);
}
try (InitTimer rt = timer("create Bytecode provider")) {
- bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
+ bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection);
}
try (InitTimer rt = timer("create Replacements provider")) {
- replacements = createReplacements(p, snippetReflection, bytecodeProvider);
+ replacements = createReplacements(target, p, snippetReflection, bytecodeProvider);
}
try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, options);
@@ -148,8 +155,7 @@
suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options);
}
providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
- snippetReflection, wordTypes,
- plugins);
+ snippetReflection, wordTypes, plugins, gc);
replacements.setProviders(providers);
}
try (InitTimer rt = timer("instantiate backend")) {
@@ -161,7 +167,7 @@
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options);
- AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9, config.useFMAIntrinsics);
+ AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JavaVersionUtil.JAVA_SPEC >= 9, config.useFMAIntrinsics);
return plugins;
}
@@ -173,10 +179,6 @@
return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp);
}
- protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
- return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget());
- }
-
protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess,
HotSpotCodeCacheProvider codeCache, WordTypes wordTypes, Value[] nativeABICallerSaveRegisters) {
return new AMD64HotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
@@ -191,10 +193,6 @@
new AddressLoweringPhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options)));
}
- protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) {
- return new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes);
- }
-
protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls,
HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, target);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -104,6 +104,8 @@
registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_TWO_CONSECUTIVE_BYTES, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS, options, providers,
registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS_COMPACT, options, providers,
+ registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS_COMPACT, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_1_BYTE, options, providers,
registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_1_BYTE, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_2_BYTES, options, providers,
@@ -120,6 +122,14 @@
registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_3_CHARS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, options, providers,
registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_1_CHAR_COMPACT, options, providers,
+ registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_1_CHAR_COMPACT, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_2_CHARS_COMPACT, options, providers,
+ registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_2_CHARS_COMPACT, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_3_CHARS_COMPACT, options, providers,
+ registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_3_CHARS_COMPACT, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+ link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS_COMPACT, options, providers,
+ registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS_COMPACT, LEAF, REEXECUTABLE, NO_LOCATIONS)));
link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, options, providers,
registerStubCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Fri Jun 28 14:36:42 2019 +0530
@@ -71,7 +71,7 @@
// Discard the return address, thus completing restoration of caller frame
masm.incrementq(rsp, 8);
- if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
+ if (JavaVersionUtil.JAVA_SPEC < 8) {
// Restore rsp from rbp if the exception PC is a method handle call site.
AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset);
masm.cmpl(dst, 0);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,7 +24,6 @@
package org.graalvm.compiler.hotspot.amd64;
-import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
import org.graalvm.compiler.api.replacements.Snippet;
@@ -43,6 +42,7 @@
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.amd64.AMD64ArrayIndexOfDispatchNode;
import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
@@ -67,9 +67,12 @@
@Override
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
- profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options)
- ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget())
- : null;
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
+ // AOT only introduced in JDK 9
+ profileSnippets = null;
+ } else {
+ profileSnippets = new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget());
+ }
mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
super.initialize(options, factories, providers, config);
}
@@ -82,6 +85,8 @@
profileSnippets.lower((ProfileNode) n, tool);
} else if (n instanceof UnaryMathIntrinsicNode) {
lowerUnaryMath((UnaryMathIntrinsicNode) n, tool);
+ } else if (n instanceof AMD64ArrayIndexOfDispatchNode) {
+ lowerArrayIndexOf((AMD64ArrayIndexOfDispatchNode) n);
} else {
super.lower(n, tool);
}
@@ -125,6 +130,12 @@
math.replaceAtUsages(call);
}
+ private void lowerArrayIndexOf(AMD64ArrayIndexOfDispatchNode dispatchNode) {
+ StructuredGraph graph = dispatchNode.graph();
+ ForeignCallNode call = graph.add(new ForeignCallNode(foreignCalls, dispatchNode.getStubCallDescriptor(), dispatchNode.getStubCallArgs()));
+ graph.replaceFixed(dispatchNode, call);
+ }
+
@Override
public Integer smallestCompareWidth() {
return 8;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/MathDoubleFMATest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/MathDoubleFMATest.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,7 +30,10 @@
import java.util.Collection;
import java.util.List;
+import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.runtime.RuntimeProvider;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +51,8 @@
@Before
public void checkAMD64() {
assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
+ HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class);
+ assumeTrue("skipping FMA specific test", rt.getVMConfig().useFMAIntrinsics);
}
@Parameters(name = "{0}, {1}, {2}")
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/MathFloatFMATest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/MathFloatFMATest.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,7 +30,10 @@
import java.util.Collection;
import java.util.List;
+import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.runtime.RuntimeProvider;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +51,8 @@
@Before
public void checkAMD64() {
assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
+ HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class);
+ assumeTrue("skipping FMA specific tests", rt.getVMConfig().useFMAIntrinsics);
}
@Parameters(name = "{0}, {1}, {2}")
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,6 +32,7 @@
import org.graalvm.compiler.nodes.java.NewArrayNode;
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.AddExports;
import org.junit.Test;
@@ -49,7 +50,7 @@
private static final int N_OVERFLOW = 10;
public StringUTF16ToBytesGetCharsTest() {
- assumeFalse(Java8OrEarlier);
+ assumeFalse(JavaVersionUtil.JAVA_SPEC <= 8);
}
@Test
@@ -57,7 +58,7 @@
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "toBytes", char[].class, int.class, int.class);
- StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+ StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), null);
assertInGraph(graph, NewArrayNode.class);
assertInGraph(graph, ArrayCopyCallNode.class);
@@ -88,7 +89,7 @@
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "getChars", byte[].class, int.class, int.class, char[].class, int.class);
- StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+ StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), null);
assertInGraph(graph, ArrayCopyCallNode.class);
InstalledCode code = getCode(caller, graph);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/MitigateExceedingMaxOopMapStackOffsetTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.lir.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.hotspot.HotSpotBackend;
+import org.graalvm.compiler.lir.VirtualStackSlot;
+import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+import org.graalvm.compiler.lir.jtt.LIRTest;
+import org.graalvm.compiler.lir.jtt.LIRTestSpecification;
+import org.graalvm.compiler.lir.stackslotalloc.LSStackSlotAllocator;
+import org.graalvm.compiler.nodes.SafepointNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
+import org.junit.Assume;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Tests the mitigation against overflowing the max size limit for a HotSpot OopMap. The mitigation
+ * works by {@link LSStackSlotAllocator} placing reference typed stack slots at lower offsets.
+ */
+public class MitigateExceedingMaxOopMapStackOffsetTest extends LIRTest {
+
+ /**
+ * Allocate stacks slots and initializes those at an odd index with a reference constant and
+ * those at an even index with a primitive constant.
+ */
+ private static class WriteStackValues extends LIRTestSpecification {
+ private final JavaConstant objectConstant;
+ private final JavaConstant primitiveConstant;
+
+ WriteStackValues(JavaConstant objectConstant, JavaConstant primitiveConstant) {
+ this.objectConstant = objectConstant;
+ this.primitiveConstant = primitiveConstant;
+ }
+
+ @Override
+ public void generate(LIRGeneratorTool gen) {
+ FrameMapBuilder frameMapBuilder = gen.getResult().getFrameMapBuilder();
+ LIRKind objectLirKind = LIRKind.reference(gen.target().arch.getPlatformKind(objectConstant.getJavaKind()));
+ LIRKind primitiveLirKind = LIRKind.value(gen.target().arch.getPlatformKind(primitiveConstant.getJavaKind()));
+
+ int numSlots = numPrimitiveSlots + numReferenceSlots;
+ List<AllocatableValue> slotList = new ArrayList<>(numSlots);
+ // Place reference slots at top and bottom of virtual frame
+ // with primitive slots in the middle. This tests that slot
+ // partitioning works.
+ for (int i = 0; i < numReferenceSlots / 2; i++) {
+ AllocatableValue src = gen.emitLoadConstant(objectLirKind, objectConstant);
+ VirtualStackSlot slot = frameMapBuilder.allocateSpillSlot(objectLirKind);
+ slotList.add(slot);
+ gen.emitMove(slot, src);
+ }
+ for (int i = 0; i < numPrimitiveSlots; i++) {
+ AllocatableValue src = gen.emitLoadConstant(objectLirKind, primitiveConstant);
+ VirtualStackSlot slot = frameMapBuilder.allocateSpillSlot(primitiveLirKind);
+ slotList.add(slot);
+ gen.emitMove(slot, src);
+ }
+ for (int i = numReferenceSlots / 2; i < numReferenceSlots; i++) {
+ AllocatableValue src = gen.emitLoadConstant(objectLirKind, objectConstant);
+ VirtualStackSlot slot = frameMapBuilder.allocateSpillSlot(objectLirKind);
+ slotList.add(slot);
+ gen.emitMove(slot, src);
+ }
+ slots = slotList.toArray(new AllocatableValue[slotList.size()]);
+ }
+ }
+
+ /**
+ * Read stacks slots and move their content into a blackhole.
+ */
+ private static class ReadStackValues extends LIRTestSpecification {
+
+ ReadStackValues() {
+ }
+
+ @Override
+ public void generate(LIRGeneratorTool gen) {
+ for (int i = 0; i < slots.length; i++) {
+ gen.emitBlackhole(gen.emitMove(slots[i]));
+ }
+ }
+ }
+
+ @Override
+ protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
+ InvocationPlugin safepointPlugin = new InvocationPlugin() {
+ @Override
+ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
+ b.add(new SafepointNode());
+ return true;
+ }
+ };
+ conf.getPlugins().getInvocationPlugins().register(safepointPlugin, getClass(), "safepoint");
+ return super.editGraphBuilderConfiguration(conf);
+ }
+
+ /*
+ * Safepoint Snippet
+ */
+ private static void safepoint() {
+ }
+
+ private static int numPrimitiveSlots;
+ private static int numReferenceSlots;
+ private static AllocatableValue[] slots;
+
+ private static final LIRTestSpecification readStackValues = new ReadStackValues();
+
+ @SuppressWarnings("unused")
+ @LIRIntrinsic
+ public static void instrinsic(LIRTestSpecification spec) {
+ }
+
+ private static final LIRTestSpecification writeStackValues = new WriteStackValues(JavaConstant.NULL_POINTER, JavaConstant.LONG_0);
+
+ public void testStackObjects() {
+ instrinsic(writeStackValues);
+ safepoint();
+ instrinsic(readStackValues);
+ }
+
+ @Test
+ public void runStackObjects() throws Throwable {
+ int max = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig().maxOopMapStackOffset;
+ Assume.assumeFalse("no limit on oop map size", max == Integer.MAX_VALUE);
+ numPrimitiveSlots = (max / 8) * 2;
+ numReferenceSlots = (max / 8) - 100; // Should be enough margin for all platforms
+ runTest("testStackObjects");
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Fri Jun 28 14:36:42 2019 +0530
@@ -38,7 +38,7 @@
import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotConstantFieldProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
-import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotGCProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
@@ -55,7 +55,6 @@
import org.graalvm.compiler.phases.common.AddressLoweringPhase;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
-import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
import org.graalvm.compiler.replacements.sparc.SPARCGraphBuilderPlugins;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
@@ -72,7 +71,7 @@
import jdk.vm.ci.sparc.SPARC;
@ServiceProvider(HotSpotBackendFactory.class)
-public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory {
+public class SPARCHotSpotBackendFactory extends HotSpotBackendFactory {
@Override
public String getName() {
@@ -95,22 +94,22 @@
HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmci.getCodeCache();
TargetDescription target = codeCache.getTarget();
HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection();
- HotSpotConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess);
+ HotSpotConstantFieldProvider constantFieldProvider = createConstantFieldProvider(config, metaAccess);
Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(config, codeCache.getRegisterConfig());
- HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind);
+ HotSpotWordTypes wordTypes = createWordTypes(metaAccess, target);
HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
LoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, constantReflection, target);
- HotSpotStampProvider stampProvider = new HotSpotStampProvider();
- Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider);
- HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes);
- BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
- HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target);
+ HotSpotStampProvider stampProvider = createStampProvider();
+ HotSpotGCProvider gc = createGCProvider(config);
+ Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, gc);
+ HotSpotSnippetReflectionProvider snippetReflection = createSnippetReflection(runtime, constantReflection, wordTypes);
+ BytecodeProvider bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection);
+ HotSpotReplacementsImpl replacements = createReplacements(target, p, snippetReflection, bytecodeProvider);
Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, snippetReflection, replacements, wordTypes, runtime.getOptions());
replacements.setGraphBuilderPlugins(plugins);
HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements);
HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
- snippetReflection,
- wordTypes, plugins);
+ snippetReflection, wordTypes, plugins, gc);
replacements.setProviders(providers);
return createBackend(config, runtime, providers);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BoxDeoptimizationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BoxDeoptimizationTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -4,9 +4,7 @@
*
* 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.
+ * 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
@@ -22,6 +20,8 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
+
package org.graalvm.compiler.hotspot.test;
import org.graalvm.compiler.api.directives.GraalDirectives;
@@ -32,7 +32,7 @@
import org.junit.Test;
public class BoxDeoptimizationTest extends GraalCompilerTest {
- private static boolean isJDK13OrLater = JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 13;
+ private static boolean isJDK13OrLater = JavaVersionUtil.JAVA_SPEC >= 13;
public static void testInteger() {
Object[] values = {42, new Exception()};
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CRC32CSubstitutionsTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CRC32CSubstitutionsTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,22 +24,20 @@
package org.graalvm.compiler.hotspot.test;
+import static org.junit.Assume.assumeFalse;
+
import java.io.DataInputStream;
import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.zip.Checksum;
-
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
-
-import org.graalvm.compiler.test.GraalTest;
-import org.graalvm.compiler.core.test.GraalCompilerTest;
+import java.nio.ByteBuffer;
+import java.util.zip.Checksum;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.junit.Test;
-import static org.junit.Assume.assumeFalse;
-
/**
* Tests compiled calls to {@link java.util.zip.CRC32C}.
*/
@@ -56,7 +54,7 @@
@Test
public void test1() throws Throwable {
- assumeFalse(GraalTest.Java8OrEarlier);
+ assumeFalse(JavaVersionUtil.JAVA_SPEC <= 8);
String classfileName = CRC32CSubstitutionsTest.class.getSimpleName().replace('.', '/') + ".class";
InputStream s = CRC32CSubstitutionsTest.class.getResourceAsStream(classfileName);
byte[] buf = new byte[s.available()];
@@ -79,7 +77,7 @@
@Test
public void test2() throws Throwable {
- assumeFalse(GraalTest.Java8OrEarlier);
+ assumeFalse(JavaVersionUtil.JAVA_SPEC <= 8);
String classfileName = CRC32CSubstitutionsTest.class.getSimpleName().replace('.', '/') + ".class";
InputStream s = CRC32CSubstitutionsTest.class.getResourceAsStream(classfileName);
byte[] buf = new byte[s.available()];
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Fri Jun 28 14:36:42 2019 +0530
@@ -386,6 +386,10 @@
if (isJDK11OrHigher()) {
// Relevant for Java flight recorder
add(toBeInvestigated,
+ "java/lang/CharacterDataLatin1.isDigit(I)Z",
+ "java/lang/CharacterDataLatin1.isLowerCase(I)Z",
+ "java/lang/CharacterDataLatin1.isUpperCase(I)Z",
+ "java/lang/CharacterDataLatin1.isWhitespace(I)Z",
"jdk/jfr/internal/JVM.getEventWriter()Ljava/lang/Object;");
if (!config.useBase64Intrinsics()) {
add(ignore,
@@ -393,14 +397,6 @@
}
}
- if (isJDK12OrHigher()) {
- add(toBeInvestigated,
- "java/lang/CharacterDataLatin1.isDigit(I)Z",
- "java/lang/CharacterDataLatin1.isLowerCase(I)Z",
- "java/lang/CharacterDataLatin1.isUpperCase(I)Z",
- "java/lang/CharacterDataLatin1.isWhitespace(I)Z");
- }
-
if (isJDK13OrHigher()) {
add(toBeInvestigated,
"java/lang/Math.abs(I)I",
@@ -568,23 +564,23 @@
}
private static boolean isJDK9OrHigher() {
- return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9;
+ return JavaVersionUtil.JAVA_SPEC >= 9;
}
private static boolean isJDK10OrHigher() {
- return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 10;
+ return JavaVersionUtil.JAVA_SPEC >= 10;
}
private static boolean isJDK11OrHigher() {
- return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 11;
+ return JavaVersionUtil.JAVA_SPEC >= 11;
}
private static boolean isJDK12OrHigher() {
- return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 12;
+ return JavaVersionUtil.JAVA_SPEC >= 12;
}
private static boolean isJDK13OrHigher() {
- return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 13;
+ return JavaVersionUtil.JAVA_SPEC >= 13;
}
public interface Refiner {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,7 +31,6 @@
import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
import java.io.ByteArrayOutputStream;
@@ -97,6 +96,7 @@
import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.internal.vm.compiler.libgraal.LibGraal;
+import jdk.internal.vm.compiler.libgraal.LibGraalScope;
import jdk.internal.vm.compiler.libgraal.OptionsEncoder;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
@@ -117,9 +117,8 @@
public final class CompileTheWorld {
/**
- * Magic token to denote that JDK classes are to be compiled. If
- * {@link JavaVersionUtil#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled.
- * Otherwise the classes in the Java runtime image are compiled.
+ * Magic token to denote that JDK classes are to be compiled. For JDK 8, the classes in
+ * {@code rt.jar} are compiled. Otherwise the classes in the Java runtime image are compiled.
*/
public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";
@@ -398,7 +397,7 @@
try (LibGraalParams libgraal = LibGraal.isAvailable() ? new LibGraalParams(compilerOptions) : null) {
if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) {
String bcpEntry = null;
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
final String[] entries = System.getProperty(SUN_BOOT_CLASS_PATH).split(File.pathSeparator);
for (int i = 0; i < entries.length && bcpEntry == null; i++) {
String entry = entries[i];
@@ -940,6 +939,7 @@
/**
* Compiles a method and gathers some statistics.
*/
+ @SuppressWarnings("try")
private void compileMethod(HotSpotResolvedJavaMethod method, int counter, LibGraalParams libgraal) {
try {
long start = System.currentTimeMillis();
@@ -950,32 +950,33 @@
HotSpotInstalledCode installedCode;
if (libgraal != null) {
HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
- long methodHandle = LibGraal.translate(runtime, method);
- long isolateThread = LibGraal.getIsolateThread();
+ try (LibGraalScope scope = new LibGraalScope(runtime)) {
+ long methodHandle = LibGraal.translate(runtime, method);
+ long isolateThread = LibGraalScope.getIsolateThread();
- StackTraceBuffer stackTraceBuffer = libgraal.getStackTraceBuffer();
+ StackTraceBuffer stackTraceBuffer = libgraal.getStackTraceBuffer();
- long stackTraceBufferAddress = stackTraceBuffer.getAddress();
- long installedCodeHandle = compileMethodInLibgraal(isolateThread,
- methodHandle,
- useProfilingInfo,
- installAsDefault,
- libgraal.options.getAddress(),
- libgraal.options.size,
- libgraal.options.hash,
- stackTraceBufferAddress,
- stackTraceBuffer.size);
+ long stackTraceBufferAddress = stackTraceBuffer.getAddress();
+ long installedCodeHandle = compileMethodInLibgraal(isolateThread,
+ methodHandle,
+ useProfilingInfo,
+ installAsDefault,
+ libgraal.options.getAddress(),
+ libgraal.options.size,
+ libgraal.options.hash,
+ stackTraceBufferAddress,
+ stackTraceBuffer.size);
- installedCode = LibGraal.unhand(runtime, HotSpotInstalledCode.class, installedCodeHandle);
- if (installedCode == null) {
- int length = UNSAFE.getInt(stackTraceBufferAddress);
- byte[] data = new byte[length];
- UNSAFE.copyMemory(null, stackTraceBufferAddress + Integer.BYTES, data, ARRAY_BYTE_BASE_OFFSET, length);
- String stackTrace = new String(data).trim();
- println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r"));
- println(stackTrace);
+ installedCode = LibGraal.unhand(runtime, HotSpotInstalledCode.class, installedCodeHandle);
+ if (installedCode == null) {
+ int length = UNSAFE.getInt(stackTraceBufferAddress);
+ byte[] data = new byte[length];
+ UNSAFE.copyMemory(null, stackTraceBufferAddress + Integer.BYTES, data, ARRAY_BYTE_BASE_OFFSET, length);
+ String stackTrace = new String(data).trim();
+ println("CompileTheWorld (%d) : Error compiling method: %s", counter, method.format("%H.%n(%p):%r"));
+ println(stackTrace);
+ }
}
-
} else {
int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,6 +35,7 @@
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.JLModule;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -75,8 +76,8 @@
}
private static Object getConstantPoolForObject() {
- String miscPackage = Java8OrEarlier ? "sun.misc"
- : (Java11OrEarlier ? "jdk.internal.misc" : "jdk.internal.access");
+ String miscPackage = JavaVersionUtil.JAVA_SPEC <= 8 ? "sun.misc"
+ : (JavaVersionUtil.JAVA_SPEC <= 11 ? "jdk.internal.misc" : "jdk.internal.access");
try {
Class<?> sharedSecretsClass = Class.forName(miscPackage + ".SharedSecrets");
Class<?> javaLangAccessClass = Class.forName(miscPackage + ".JavaLangAccess");
@@ -111,11 +112,11 @@
* This test uses some API hidden by the JDK9 module system.
*/
private static void addExports(Class<?> c) {
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
Object javaBaseModule = JLModule.fromClass(String.class);
Object cModule = JLModule.fromClass(c);
uncheckedAddExports(javaBaseModule, "jdk.internal.reflect", cModule);
- if (Java11OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 11) {
uncheckedAddExports(javaBaseModule, "jdk.internal.misc", cModule);
} else {
uncheckedAddExports(javaBaseModule, "jdk.internal.access", cModule);
@@ -222,7 +223,7 @@
cw.visit(52, ACC_SUPER, PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", null, "java/lang/Object", null);
cw.visitInnerClass(PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", PACKAGE_NAME_INTERNAL + "/ConstantPoolSubstitutionsTests", "ConstantPoolTest",
ACC_STATIC);
- String constantPool = Java8OrEarlier ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool";
+ String constantPool = JavaVersionUtil.JAVA_SPEC <= 8 ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool";
mv = cw.visitMethod(0, "<init>", "()V", null, null);
mv.visitCode();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DeferredBarrierAdditionTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.gc.G1PostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ReferentFieldReadBarrier;
+import org.graalvm.compiler.nodes.gc.SerialWriteBarrier;
+import org.graalvm.compiler.nodes.java.AbstractNewObjectNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.common.GuardLoweringPhase;
+import org.graalvm.compiler.phases.common.LoweringPhase;
+import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase;
+import org.graalvm.compiler.phases.common.inlining.InliningPhase;
+import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.graalvm.compiler.phases.tiers.MidTierContext;
+import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * This tests that barriers which are deferrable because of ReduceInitialCardMarks are properly
+ * omitted. The rule is simply that only writes to the very last allocated object can skip the card
+ * mark. By creating references between objects only one write can skip the card mark and the other
+ * must emit a card mark.
+ */
+public class DeferredBarrierAdditionTest extends HotSpotGraalCompilerTest {
+
+ private final GraalHotSpotVMConfig config = runtime().getVMConfig();
+
+ public static Object testCrossReferences() {
+ Object[] a = new Object[1];
+ Object[] b = new Object[1];
+ a[0] = b;
+ b[0] = a;
+ return a;
+ }
+
+ @Test
+ public void testGroupAllocation() throws Exception {
+ testHelper("testCrossReferences", 1, getInitialOptions());
+ }
+
+ @SuppressWarnings("try")
+ protected void testHelper(final String snippetName, final int expectedBarriers, OptionValues options) {
+ ResolvedJavaMethod snippet = getResolvedJavaMethod(snippetName);
+ DebugContext debug = getDebugContext(options, null, snippet);
+ try (DebugContext.Scope s = debug.scope("WriteBarrierAdditionTest", snippet)) {
+ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug);
+ HighTierContext highContext = getDefaultHighTierContext();
+ MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
+ new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext);
+ new CanonicalizerPhase().apply(graph, highContext);
+ new PartialEscapePhase(false, new CanonicalizerPhase(), debug.getOptions()).apply(graph, highContext);
+ new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext);
+ new GuardLoweringPhase().apply(graph, midContext);
+ new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
+ new WriteBarrierAdditionPhase().apply(graph, midContext);
+ debug.dump(DebugContext.BASIC_LEVEL, graph, "After Write Barrier Addition");
+
+ checkAssumptions(graph);
+
+ int barriers = 0;
+ if (config.useG1GC) {
+ barriers = graph.getNodes().filter(G1ReferentFieldReadBarrier.class).count() + graph.getNodes().filter(G1PreWriteBarrier.class).count() +
+ graph.getNodes().filter(G1PostWriteBarrier.class).count();
+ } else {
+ barriers = graph.getNodes().filter(SerialWriteBarrier.class).count();
+ }
+ if (expectedBarriers != barriers) {
+ Assert.assertEquals(getScheduledGraphString(graph), expectedBarriers, barriers);
+ }
+ } catch (Throwable e) {
+ throw debug.handle(e);
+ }
+ }
+
+ protected void checkAssumptions(StructuredGraph graph) {
+ assumeTrue(graph.getNodes().filter(AbstractNewObjectNode.class).isNotEmpty());
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,7 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
- * A Graal compiler test that needs access to the {@link HotSpotGraalRuntimeProvider}.
+ * A compiler test that needs access to the {@link HotSpotGraalRuntimeProvider}.
*/
public abstract class HotSpotGraalCompilerTest extends GraalCompilerTest {
@@ -73,7 +73,7 @@
HotSpotProviders providers = rt.getHostBackend().getProviders();
CompilationIdentifier compilationId = runtime().getHostBackend().getCompilationIdentifier(method);
OptionValues options = getInitialOptions();
- StructuredGraph graph = providers.getReplacements().getIntrinsicGraph(method, compilationId, getDebugContext(options));
+ StructuredGraph graph = providers.getReplacements().getIntrinsicGraph(method, compilationId, getDebugContext(options), null);
if (graph != null) {
return getCode(method, graph, true, true, graph.getOptions());
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotInvokeDynamicPluginTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,12 +24,12 @@
package org.graalvm.compiler.hotspot.test;
-import java.util.function.IntPredicate;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
import java.security.PrivilegedAction;
+import java.util.function.IntPredicate;
+
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin;
@@ -37,22 +37,24 @@
import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicStubCall;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo;
-import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase;
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.tiers.MidTierContext;
import org.junit.Assert;
import org.junit.Test;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
public class HotSpotInvokeDynamicPluginTest extends HotSpotGraalCompilerTest {
@Override
protected Plugins getDefaultGraphBuilderPlugins() {
@@ -94,7 +96,7 @@
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveDynamicConstantNode.class).count());
Assert.assertEquals(0, graph.getNodes().filter(ResolveDynamicStubCall.class).count());
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
new GuardLoweringPhase().apply(graph, midTierContext);
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HsErrLogTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HsErrLogTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -39,6 +39,7 @@
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.SubprocessUtil;
import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
import org.junit.Assert;
@@ -54,7 +55,7 @@
@Test
public void test1() throws IOException, InterruptedException {
List<String> args = new ArrayList<>();
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
args.add("-XX:-UseJVMCIClassLoader");
}
args.add("-XX:+UseJVMCICompiler");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -73,13 +73,12 @@
}
@Override
- protected boolean checkLowTierGraph(StructuredGraph graph) {
+ protected void checkLowTierGraph(StructuredGraph graph) {
for (ConstantNode constantNode : graph.getNodes().filter(ConstantNode.class)) {
assert constantNode.asJavaConstant() == null || constantNode.asJavaConstant().getJavaKind() != JavaKind.Object ||
constantNode.asJavaConstant().isDefaultForKind() : "Found unexpected object constant " +
constantNode + ", this should have been removed by the LoadJavaMirrorWithKlassPhase.";
}
- return true;
}
public static Class<?> classConstant() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectHashCodeInliningTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectHashCodeInliningTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -42,7 +42,7 @@
@Test
public void testInstallCodeInvalidation() {
for (int i = 0; i < 100000; i++) {
- getHash(i % 1000 == 0 ? new Object() : "");
+ getHash(i % 10 == 0 ? new Object() : "");
}
ResolvedJavaMethod method = getResolvedJavaMethod("getHash");
@@ -74,8 +74,9 @@
}
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
- return containsForeignCallToIdentityHashCode(graph) && containsReadStringHash(graph);
+ protected void checkHighTierGraph(StructuredGraph graph) {
+ assert containsForeignCallToIdentityHashCode(graph) : "expected a foreign call to identity_hashcode";
+ assert containsReadStringHash(graph) : "expected a read from String.hash";
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Fri Jun 28 14:36:42 2019 +0530
@@ -72,7 +72,7 @@
if (plugin instanceof MethodSubstitutionPlugin) {
ResolvedJavaMethod method = CheckGraalIntrinsics.resolveIntrinsic(getMetaAccess(), intrinsic);
if (!method.isNative()) {
- StructuredGraph graph = providers.getReplacements().getIntrinsicGraph(method, INVALID_COMPILATION_ID, debug);
+ StructuredGraph graph = providers.getReplacements().getIntrinsicGraph(method, INVALID_COMPILATION_ID, debug, null);
getCode(method, graph);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,13 +32,12 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase;
-import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1ReferentFieldReadBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
-import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.gc.G1PostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ReferentFieldReadBarrier;
+import org.graalvm.compiler.nodes.gc.SerialWriteBarrier;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
@@ -50,13 +49,12 @@
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
+import org.graalvm.compiler.phases.common.WriteBarrierAdditionPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.MidTierContext;
import org.graalvm.compiler.replacements.NodeIntrinsificationProvider;
-import org.graalvm.compiler.word.Word;
-import jdk.internal.vm.compiler.word.WordFactory;
import org.junit.Assert;
import org.junit.Test;
@@ -257,34 +255,6 @@
test2("testArrayCopy", src, dst, dst.length);
}
- public static class WordContainer {
- public Word word;
- }
-
- public static void testWordFieldSnippet() {
- WordContainer wordContainer = new WordContainer();
- wordContainer.word = WordFactory.signed(42);
- }
-
- @Test
- public void testWordField() throws Exception {
- testHelper("testWordFieldSnippet", 0);
- }
-
- public static Word[] testWordArraySnippet(int length) {
- Word fortyTwo = WordFactory.signed(42);
- Word[] words = new Word[length];
- for (int i = 0; i < length; i++) {
- words[i] = fortyTwo;
- }
- return words;
- }
-
- @Test
- public void testWordArray() throws Exception {
- testHelper("testWordArraySnippet", 0);
- }
-
public static Object testUnsafeLoad(Unsafe theUnsafe, Object a, Object b, Object c) throws Exception {
final int offset = (c == null ? 0 : ((Integer) c).intValue());
final long displacement = (b == null ? 0 : ((Long) b).longValue());
@@ -311,7 +281,7 @@
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext);
new GuardLoweringPhase().apply(graph, midContext);
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
- new WriteBarrierAdditionPhase(config).apply(graph);
+ new WriteBarrierAdditionPhase().apply(graph, midContext);
debug.dump(DebugContext.BASIC_LEVEL, graph, "After Write Barrier Addition");
int barriers = 0;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,737 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.test;
-
-import java.util.List;
-
-import jdk.internal.vm.compiler.collections.EconomicMap;
-import org.graalvm.compiler.debug.DebugCloseable;
-import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.DebugContext.Scope;
-import org.graalvm.compiler.debug.DebugDumpScope;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePreWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialArrayRangeWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
-import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
-import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
-import org.graalvm.compiler.nodes.AbstractBeginNode;
-import org.graalvm.compiler.nodes.AbstractMergeNode;
-import org.graalvm.compiler.nodes.FieldLocationIdentity;
-import org.graalvm.compiler.nodes.FixedNode;
-import org.graalvm.compiler.nodes.FixedWithNextNode;
-import org.graalvm.compiler.nodes.LoopBeginNode;
-import org.graalvm.compiler.nodes.LoopExitNode;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
-import org.graalvm.compiler.nodes.memory.WriteNode;
-import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.compiler.phases.OptimisticOptimizations;
-import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.common.GuardLoweringPhase;
-import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase;
-import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
-import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
-import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.MidTierContext;
-import jdk.internal.vm.compiler.word.LocationIdentity;
-import org.junit.Assert;
-import org.junit.Test;
-
-import jdk.vm.ci.meta.ResolvedJavaField;
-
-/**
- * The following tests validate the write barrier verification phase. For every tested snippet, an
- * array of write barrier indices and the total write barrier number are passed as parameters. The
- * indices denote the barriers that will be manually removed. The write barrier verification phase
- * runs after the write barrier removal and depending on the result an assertion might be generated.
- * The tests anticipate the presence or not of an assertion generated by the verification phase.
- */
-public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest {
-
- public static int barrierIndex;
-
- private final GraalHotSpotVMConfig config = runtime().getVMConfig();
-
- public static class Container {
-
- public Container a;
- public Container b;
- }
-
- private static native void safepoint();
-
- public static void test1Snippet(Container main) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- safepoint();
- barrierIndex = 2;
- main.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test1() {
- test("test1Snippet", 2, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test2() {
- test("test1Snippet", 2, new int[]{2});
- }
-
- public static void test2Snippet(Container main) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- barrierIndex = 2;
- main.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test3() {
- test("test2Snippet", 2, new int[]{1});
- }
-
- @Test
- public void test4() {
- test("test2Snippet", 2, new int[]{2});
- }
-
- public static void test3Snippet(Container main, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- for (int i = 0; i < 10; i++) {
- if (test) {
- barrierIndex = 1;
- main.a = temp1;
- barrierIndex = 2;
- main.b = temp2;
- } else {
- barrierIndex = 3;
- main.a = temp1;
- barrierIndex = 4;
- main.b = temp2;
- }
- }
- }
-
- @Test(expected = AssertionError.class)
- public void test5() {
- test("test3Snippet", 4, new int[]{1, 2});
- }
-
- @Test(expected = AssertionError.class)
- public void test6() {
- test("test3Snippet", 4, new int[]{3, 4});
- }
-
- @Test(expected = AssertionError.class)
- public void test7() {
- test("test3Snippet", 4, new int[]{1});
- }
-
- @Test
- public void test8() {
- test("test3Snippet", 4, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test9() {
- test("test3Snippet", 4, new int[]{3});
- }
-
- @Test
- public void test10() {
- test("test3Snippet", 4, new int[]{4});
- }
-
- public static void test4Snippet(Container main, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- for (int i = 0; i < 10; i++) {
- if (test) {
- barrierIndex = 2;
- main.a = temp1;
- barrierIndex = 3;
- main.b = temp2;
- } else {
- barrierIndex = 4;
- main.a = temp2;
- barrierIndex = 5;
- main.b = temp1;
- }
- }
- }
-
- @Test(expected = AssertionError.class)
- public void test11() {
- test("test4Snippet", 5, new int[]{2, 3});
- }
-
- @Test(expected = AssertionError.class)
- public void test12() {
- test("test4Snippet", 5, new int[]{4, 5});
- }
-
- @Test(expected = AssertionError.class)
- public void test13() {
- test("test4Snippet", 5, new int[]{1});
- }
-
- public static void test5Snippet(Container main) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- if (main.a == main.b) {
- barrierIndex = 2;
- main.a = temp1;
- barrierIndex = 3;
- main.b = temp2;
- } else {
- barrierIndex = 4;
- main.a = temp2;
- barrierIndex = 5;
- main.b = temp1;
- }
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test14() {
- test("test5Snippet", 5, new int[]{1});
- }
-
- @Test
- public void test15() {
- test("test5Snippet", 5, new int[]{2});
- }
-
- @Test
- public void test16() {
- test("test5Snippet", 5, new int[]{4});
- }
-
- @Test
- public void test17() {
- test("test5Snippet", 5, new int[]{3});
- }
-
- @Test
- public void test18() {
- test("test5Snippet", 5, new int[]{5});
- }
-
- @Test
- public void test19() {
- test("test5Snippet", 5, new int[]{2, 3});
- }
-
- @Test
- public void test20() {
- test("test5Snippet", 5, new int[]{4, 5});
- }
-
- public static void test6Snippet(Container main, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- if (test) {
- barrierIndex = 2;
- main.a = temp1;
- barrierIndex = 3;
- main.b = temp1.a.a;
- } else {
- barrierIndex = 4;
- main.a = temp2;
- barrierIndex = 5;
- main.b = temp2.a.a;
- }
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test21() {
- test("test6Snippet", 5, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test22() {
- test("test6Snippet", 5, new int[]{1, 2});
- }
-
- @Test
- public void test23() {
- test("test6Snippet", 5, new int[]{3});
- }
-
- @Test
- public void test24() {
- test("test6Snippet", 5, new int[]{4});
- }
-
- public static void test7Snippet(Container main, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- barrierIndex = 1;
- main.a = temp1;
- if (test) {
- barrierIndex = 2;
- main.a = temp1;
- }
- barrierIndex = 3;
- main.b = temp2;
- safepoint();
- }
-
- @Test
- public void test25() {
- test("test7Snippet", 3, new int[]{2});
- }
-
- @Test
- public void test26() {
- test("test7Snippet", 3, new int[]{3});
- }
-
- @Test
- public void test27() {
- test("test7Snippet", 3, new int[]{2, 3});
- }
-
- @Test(expected = AssertionError.class)
- public void test28() {
- test("test7Snippet", 3, new int[]{1});
- }
-
- public static void test8Snippet(Container main, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main.a = temp1;
- }
- barrierIndex = 2;
- main.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test29() {
- test("test8Snippet", 2, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test30() {
- test("test8Snippet", 2, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test31() {
- test("test8Snippet", 2, new int[]{1, 2});
- }
-
- public static void test9Snippet(Container main1, Container main2, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main1.a = temp1;
- } else {
- barrierIndex = 2;
- main2.a = temp1;
- }
- barrierIndex = 3;
- main1.b = temp2;
- barrierIndex = 4;
- main2.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test32() {
- test("test9Snippet", 4, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test33() {
- test("test9Snippet", 4, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test34() {
- test("test9Snippet", 4, new int[]{3});
- }
-
- @Test(expected = AssertionError.class)
- public void test35() {
- test("test9Snippet", 4, new int[]{4});
- }
-
- @Test(expected = AssertionError.class)
- public void test36() {
- test("test9Snippet", 4, new int[]{1, 2});
- }
-
- @Test(expected = AssertionError.class)
- public void test37() {
- test("test9Snippet", 4, new int[]{3, 4});
- }
-
- public static void test10Snippet(Container main1, Container main2, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main1.a = temp1;
- barrierIndex = 2;
- main2.a = temp2;
- } else {
- barrierIndex = 3;
- main2.a = temp1;
- }
- barrierIndex = 4;
- main1.b = temp2;
- barrierIndex = 5;
- main2.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test38() {
- test("test10Snippet", 5, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test39() {
- test("test10Snippet", 5, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test40() {
- test("test10Snippet", 5, new int[]{3});
- }
-
- @Test(expected = AssertionError.class)
- public void test41() {
- test("test10Snippet", 5, new int[]{4});
- }
-
- @Test
- public void test42() {
- test("test10Snippet", 5, new int[]{5});
- }
-
- @Test(expected = AssertionError.class)
- public void test43() {
- test("test10Snippet", 5, new int[]{1, 2});
- }
-
- @Test(expected = AssertionError.class)
- public void test44() {
- test("test10Snippet", 5, new int[]{1, 2, 3});
- }
-
- @Test(expected = AssertionError.class)
- public void test45() {
- test("test10Snippet", 5, new int[]{3, 4});
- }
-
- public static void test11Snippet(Container main1, Container main2, Container main3, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- safepoint();
- if (test) {
- barrierIndex = 1;
- main1.a = temp1;
- barrierIndex = 2;
- main3.a = temp1;
- if (!test) {
- barrierIndex = 3;
- main2.a = temp2;
- } else {
- barrierIndex = 4;
- main1.a = temp2;
- barrierIndex = 5;
- main3.a = temp2;
- }
- } else {
- barrierIndex = 6;
- main1.b = temp2;
- for (int i = 0; i < 10; i++) {
- barrierIndex = 7;
- main3.a = temp1;
- }
- barrierIndex = 8;
- main3.b = temp2;
- }
- barrierIndex = 9;
- main1.b = temp2;
- barrierIndex = 10;
- main2.b = temp2;
- barrierIndex = 11;
- main3.b = temp2;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test46() {
- test("test11Snippet", 11, new int[]{1});
- }
-
- @Test(expected = AssertionError.class)
- public void test47() {
- test("test11Snippet", 11, new int[]{2});
- }
-
- @Test(expected = AssertionError.class)
- public void test48() {
- test("test11Snippet", 11, new int[]{3});
- }
-
- @Test(expected = AssertionError.class)
- public void test49() {
- test("test11Snippet", 11, new int[]{6});
- }
-
- @Test(expected = AssertionError.class)
- public void test50() {
- test("test11Snippet", 11, new int[]{7});
- }
-
- @Test(expected = AssertionError.class)
- public void test51() {
- test("test11Snippet", 11, new int[]{8});
- }
-
- @Test(expected = AssertionError.class)
- public void test52() {
- test("test11Snippet", 11, new int[]{9});
- }
-
- @Test(expected = AssertionError.class)
- public void test53() {
- test("test11Snippet", 11, new int[]{10});
- }
-
- @Test
- public void test54() {
- test("test11Snippet", 11, new int[]{4});
- }
-
- @Test
- public void test55() {
- test("test11Snippet", 11, new int[]{5});
- }
-
- @Test
- public void test56() {
- test("test11Snippet", 11, new int[]{11});
- }
-
- public static void test12Snippet(Container main, Container main1, boolean test) {
- Container temp1 = new Container();
- Container temp2 = new Container();
- barrierIndex = 0;
- safepoint();
- barrierIndex = 7;
- main1.a = temp1;
- for (int i = 0; i < 10; i++) {
- if (test) {
- barrierIndex = 1;
- main.a = temp1;
- barrierIndex = 2;
- main.b = temp2;
- } else {
- barrierIndex = 3;
- main.a = temp1;
- barrierIndex = 4;
- main.b = temp2;
- }
- }
- barrierIndex = 5;
- main.a = temp1;
- barrierIndex = 6;
- main.b = temp1;
- barrierIndex = 8;
- main1.b = temp1;
- safepoint();
- }
-
- @Test(expected = AssertionError.class)
- public void test57() {
- test("test12Snippet", 8, new int[]{5});
- }
-
- @Test
- public void test58() {
- test("test12Snippet", 8, new int[]{6});
- }
-
- @Test(expected = AssertionError.class)
- public void test59() {
- test("test12Snippet", 8, new int[]{7});
- }
-
- @Test(expected = AssertionError.class)
- public void test60() {
- test("test12Snippet", 8, new int[]{8});
- }
-
- public static void test13Snippet(Object[] a, Object[] b) {
- System.arraycopy(a, 0, b, 0, a.length);
- }
-
- private interface GraphPredicate {
- int apply(StructuredGraph graph);
- }
-
- private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) {
- GraphPredicate noCheck = noArg -> expectedBarriers;
- testPredicate(snippet, noCheck, removedBarrierIndices);
- }
-
- @SuppressWarnings("try")
- private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) {
- DebugContext debug = getDebugContext();
- try (DebugCloseable d = debug.disableIntercept(); DebugContext.Scope s = debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) {
- final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug);
- HighTierContext highTierContext = getDefaultHighTierContext();
- createInliningPhase().apply(graph, highTierContext);
-
- MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
-
- new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
- new GuardLoweringPhase().apply(graph, midTierContext);
- new LoopSafepointInsertionPhase().apply(graph);
- new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext);
-
- new WriteBarrierAdditionPhase(config).apply(graph);
-
- int barriers = 0;
- // First, the total number of expected barriers is checked.
- if (config.useG1GC) {
- barriers = graph.getNodes().filter(G1PreWriteBarrier.class).count() + graph.getNodes().filter(G1PostWriteBarrier.class).count() +
- graph.getNodes().filter(G1ArrayRangePreWriteBarrier.class).count() + graph.getNodes().filter(G1ArrayRangePostWriteBarrier.class).count();
- Assert.assertTrue(expectedBarriers.apply(graph) * 2 == barriers);
- } else {
- barriers = graph.getNodes().filter(SerialWriteBarrier.class).count() + graph.getNodes().filter(SerialArrayRangeWriteBarrier.class).count();
- Assert.assertTrue(expectedBarriers.apply(graph) == barriers);
- }
- ResolvedJavaField barrierIndexField = getMetaAccess().lookupJavaField(WriteBarrierVerificationTest.class.getDeclaredField("barrierIndex"));
- LocationIdentity barrierIdentity = new FieldLocationIdentity(barrierIndexField);
- // Iterate over all write nodes and remove barriers according to input indices.
- NodeIteratorClosure<Boolean> closure = new NodeIteratorClosure<Boolean>() {
-
- @Override
- protected Boolean processNode(FixedNode node, Boolean currentState) {
- if (node instanceof WriteNode) {
- WriteNode write = (WriteNode) node;
- LocationIdentity obj = write.getLocationIdentity();
- if (obj.equals(barrierIdentity)) {
- /*
- * A "barrierIndex" variable was found and is checked against the input
- * barrier array.
- */
- if (eliminateBarrier(write.value().asJavaConstant().asInt(), removedBarrierIndices)) {
- return true;
- }
- }
- } else if (node instanceof SerialWriteBarrier || node instanceof G1PostWriteBarrier) {
- // Remove flagged write barriers.
- if (currentState) {
- graph.removeFixed(((FixedWithNextNode) node));
- return false;
- }
- }
- return currentState;
- }
-
- private boolean eliminateBarrier(int index, int[] map) {
- for (int i = 0; i < map.length; i++) {
- if (map[i] == index) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- protected EconomicMap<LoopExitNode, Boolean> processLoop(LoopBeginNode loop, Boolean initialState) {
- return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
- }
-
- @Override
- protected Boolean merge(AbstractMergeNode merge, List<Boolean> states) {
- return false;
- }
-
- @Override
- protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
- return false;
- }
- };
-
- try (Scope disabled = debug.disable()) {
- ReentrantNodeIterator.apply(closure, graph.start(), false);
- new WriteBarrierVerificationPhase(config).apply(graph);
- } catch (AssertionError error) {
- /*
- * Catch assertion, test for expected one and re-throw in order to validate unit
- * test.
- */
- Assert.assertTrue(error.getMessage().contains("Write barrier must be present"));
- throw error;
- }
- } catch (Throwable e) {
- throw debug.handle(e);
- }
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,6 +32,8 @@
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
import java.io.PrintStream;
+import java.util.Collections;
+import java.util.List;
import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
@@ -42,7 +44,9 @@
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.DebugContext.Description;
import org.graalvm.compiler.debug.DebugDumpScope;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
@@ -85,9 +89,11 @@
}
@Override
- protected DebugContext createRetryDebugContext(OptionValues retryOptions, PrintStream logStream) {
+ protected DebugContext createRetryDebugContext(DebugContext initialDebug, OptionValues retryOptions, PrintStream logStream) {
SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection();
- return DebugContext.create(retryOptions, logStream, new GraalDebugHandlersFactory(snippetReflection));
+ Description description = initialDebug.getDescription();
+ List<DebugHandlersFactory> factories = Collections.singletonList(new GraalDebugHandlersFactory(snippetReflection));
+ return DebugContext.create(retryOptions, description, initialDebug.getGlobalMetrics(), logStream, factories);
}
@Override
@@ -183,11 +189,19 @@
}
- public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) {
+ public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime,
+ HotSpotGraalCompiler compiler,
+ HotSpotCompilationRequest request,
+ boolean useProfilingInfo,
+ boolean installAsDefault) {
this(jvmciRuntime, compiler, request, useProfilingInfo, false, installAsDefault);
}
- public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean shouldRetainLocalVariables,
+ public CompilationTask(HotSpotJVMCIRuntime jvmciRuntime,
+ HotSpotGraalCompiler compiler,
+ HotSpotCompilationRequest request,
+ boolean useProfilingInfo,
+ boolean shouldRetainLocalVariables,
boolean installAsDefault) {
this.jvmciRuntime = jvmciRuntime;
this.compiler = compiler;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,6 +28,7 @@
import java.util.Arrays;
+import org.graalvm.compiler.core.GraalServiceThread;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
@@ -49,10 +50,10 @@
* dog reports a long running compilation. Every
* {@link Options#CompilationWatchDogStackTraceInterval} seconds after that point in time where the
* same compilation is still executing, the watch dog takes a stack trace of the compiler thread. If
- * more than {@value Options#NonFatalIdenticalCompilationSnapshots} contiguous identical stack
- * traces are seen, the watch dog reports a stuck compilation and exits the VM.
+ * more than {@link Options#NonFatalIdenticalCompilationSnapshots} contiguous identical stack traces
+ * are seen, the watch dog reports a stuck compilation and exits the VM.
*/
-class CompilationWatchDog extends Thread implements AutoCloseable {
+class CompilationWatchDog implements Runnable, AutoCloseable {
public static class Options {
// @formatter:off
@@ -112,9 +113,6 @@
CompilationWatchDog(Thread compilerThread, long startDelayMilliseconds, long stackTraceIntervalMilliseconds, int nonFatalIdenticalCompilationSnapshots) {
this.compilerThread = compilerThread;
- this.setName("WatchDog" + getId() + "[" + compilerThread.getName() + "]");
- this.setPriority(Thread.MAX_PRIORITY);
- this.setDaemon(true);
this.startDelayMilliseconds = startDelayMilliseconds;
this.stackTraceIntervalMilliseconds = stackTraceIntervalMilliseconds;
this.nonFatalIdenticalCompilationSnapshots = nonFatalIdenticalCompilationSnapshots;
@@ -185,7 +183,7 @@
@Override
public String toString() {
- return getName();
+ return "WatchDog[" + compilerThread.getName() + "]";
}
@Override
@@ -305,12 +303,16 @@
// Lazily get a watch dog thread for the current compiler thread
CompilationWatchDog watchDog = WATCH_DOGS.get();
if (watchDog == null) {
- Thread currentThread = currentThread();
+ Thread currentThread = Thread.currentThread();
long stackTraceIntervalMilliseconds = ms(Options.CompilationWatchDogStackTraceInterval.getValue(options));
int nonFatalIdenticalCompilationSnapshots = Options.NonFatalIdenticalCompilationSnapshots.getValue(options);
watchDog = new CompilationWatchDog(currentThread, startDelayMilliseconds, stackTraceIntervalMilliseconds, nonFatalIdenticalCompilationSnapshots);
WATCH_DOGS.set(watchDog);
- watchDog.start();
+ GraalServiceThread thread = new GraalServiceThread(watchDog);
+ thread.setName(thread.getId() + " " + watchDog.toString());
+ thread.setPriority(Thread.MAX_PRIORITY);
+ thread.setDaemon(true);
+ thread.start();
}
watchDog.startCompilation(method, id);
return watchDog;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Fri Jun 28 14:36:42 2019 +0530
@@ -42,6 +42,7 @@
import org.graalvm.compiler.options.EnumOptionKey;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionStability;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
@@ -53,9 +54,9 @@
import jdk.vm.ci.common.InitTimer;
/**
- * A factory that creates the {@link CompilerConfiguration} the Graal compiler will use. Each
- * factory must have a unique {@link #name} and {@link #autoSelectionPriority}. The latter imposes a
- * total ordering between factories for the purpose of auto-selecting the factory to use.
+ * A factory that creates the {@link CompilerConfiguration} the compiler will use. Each factory must
+ * have a unique {@link #name} and {@link #autoSelectionPriority}. The latter imposes a total
+ * ordering between factories for the purpose of auto-selecting the factory to use.
*/
public abstract class CompilerConfigurationFactory implements Comparable<CompilerConfigurationFactory> {
@@ -67,11 +68,11 @@
static class Options {
// @formatter:off
- @Option(help = "Names the Graal compiler configuration to use. If omitted, the compiler configuration " +
+ @Option(help = "Names the compiler configuration to use. If omitted, the compiler configuration " +
"with the highest auto-selection priority is used. To see the set of available configurations, " +
- "supply the value 'help' to this option.", type = OptionType.Expert)
+ "supply the value 'help' to this option.", type = OptionType.Expert, stability = OptionStability.STABLE)
public static final OptionKey<String> CompilerConfiguration = new OptionKey<>(null);
- @Option(help = "Writes to the VM log information about the Graal compiler configuration selected.", type = OptionType.User)
+ @Option(help = "Writes to the VM log information about the compiler configuration selected.", type = OptionType.User, stability = OptionStability.STABLE)
public static final OptionKey<ShowConfigurationLevel> ShowConfiguration = new EnumOptionKey<>(ShowConfigurationLevel.none);
// @formatter:on
}
@@ -195,7 +196,7 @@
try (InitTimer t = timer("CompilerConfigurationFactory.selectFactory")) {
String value = name == null ? Options.CompilerConfiguration.getValue(options) : name;
if ("help".equals(value)) {
- System.out.println("The available Graal compiler configurations are:");
+ System.out.println("The available compiler configurations are:");
for (CompilerConfigurationFactory candidate : getAllCandidates()) {
System.out.println(" " + candidate.name);
}
@@ -208,7 +209,7 @@
}
}
if (factory == null) {
- throw new GraalError("Graal compiler configuration '%s' not found. Available configurations are: %s", value,
+ throw new GraalError("Compiler configuration '%s' not found. Available configurations are: %s", value,
getAllCandidates().stream().map(c -> c.name).collect(Collectors.joining(", ")));
}
} else {
@@ -247,7 +248,7 @@
private static void printConfigInfo(CompilerConfigurationFactory factory) {
URL location = factory.getClass().getResource(factory.getClass().getSimpleName() + ".class");
- TTY.printf("Using Graal compiler configuration '%s' provided by %s loaded from %s%n", factory.name, factory.getClass().getName(), location);
+ TTY.printf("Using compiler configuration '%s' provided by %s loaded from %s%n", factory.name, factory.getClass().getName(), location);
}
private static <C> List<String> phaseNames(PhaseSuite<C> suite) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Fri Jun 28 14:36:42 2019 +0530
@@ -97,7 +97,7 @@
public static class Options {
// @formatter:off
@Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible")
- public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9);
+ public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPEC >= 9);
@Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." +
" Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug)
public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,25 +24,64 @@
package org.graalvm.compiler.hotspot;
+import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotGCProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider;
+import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.phases.util.Providers;
+import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
+
+public abstract class HotSpotBackendFactory {
+
+ protected HotSpotGraalConstantFieldProvider createConstantFieldProvider(GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess) {
+ return new HotSpotGraalConstantFieldProvider(config, metaAccess);
+ }
+
+ protected HotSpotWordTypes createWordTypes(HotSpotMetaAccessProvider metaAccess, TargetDescription target) {
+ return new HotSpotWordTypes(metaAccess, target.wordJavaKind);
+ }
-public interface HotSpotBackendFactory {
+ protected HotSpotStampProvider createStampProvider() {
+ return new HotSpotStampProvider();
+ }
+
+ protected HotSpotGCProvider createGCProvider(GraalHotSpotVMConfig config) {
+ return new HotSpotGCProvider(config);
+ }
+
+ protected HotSpotReplacementsImpl createReplacements(TargetDescription target, Providers p, HotSpotSnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) {
+ return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target);
+ }
+
+ protected ClassfileBytecodeProvider createBytecodeProvider(HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection) {
+ return new ClassfileBytecodeProvider(metaAccess, snippetReflection);
+ }
+
+ protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, HotSpotWordTypes wordTypes) {
+ return new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes);
+ }
/**
* Gets the name of this backend factory. This should not include the {@link #getArchitecture()
* architecture}. The {@link CompilerConfigurationFactory} can select alternative backends based
* on this name.
*/
- String getName();
+ public abstract String getName();
/**
* Gets the class describing the architecture the backend created by this factory is associated
* with.
*/
- Class<? extends Architecture> getArchitecture();
+ public abstract Class<? extends Architecture> getArchitecture();
- HotSpotBackend createBackend(HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host);
+ public abstract HotSpotBackend createBackend(HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Fri Jun 28 14:36:42 2019 +0530
@@ -48,6 +48,7 @@
import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.lir.phases.LIRSuites;
+import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
@@ -74,7 +75,7 @@
import jdk.vm.ci.runtime.JVMCICompiler;
import sun.misc.Unsafe;
-public class HotSpotGraalCompiler implements GraalJVMCICompiler {
+public class HotSpotGraalCompiler implements GraalJVMCICompiler, Cancellable {
private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe();
private final HotSpotJVMCIRuntime jvmciRuntime;
@@ -86,7 +87,7 @@
HotSpotGraalCompiler(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, OptionValues options) {
this.jvmciRuntime = jvmciRuntime;
this.graalRuntime = graalRuntime;
- // It is sufficient to have one compilation counter object per Graal compiler object.
+ // It is sufficient to have one compilation counter object per compiler object.
this.compilationCounters = Options.CompilationCountLimit.getValue(options) > 0 ? new CompilationCounters(options) : null;
this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !DebugOptions.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null;
}
@@ -111,7 +112,7 @@
@SuppressWarnings("try")
CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues initialOptions) {
if (graalRuntime.isShutdown()) {
- return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false);
+ return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), true);
}
ResolvedJavaMethod method = request.getMethod();
@@ -164,19 +165,31 @@
return false;
}
+ @Override
+ public boolean isCancelled() {
+ return graalRuntime.isShutdown();
+ }
+
public StructuredGraph createGraph(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
HotSpotBackend backend = graalRuntime.getHostBackend();
HotSpotProviders providers = backend.getProviders();
final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
- StructuredGraph graph = method.isNative() || isOSR ? null : providers.getReplacements().getIntrinsicGraph(method, compilationId, debug);
+ StructuredGraph graph = method.isNative() || isOSR ? null : providers.getReplacements().getIntrinsicGraph(method, compilationId, debug, this);
if (graph == null) {
SpeculationLog speculationLog = method.getSpeculationLog();
if (speculationLog != null) {
speculationLog.collectFailedSpeculations();
}
- graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog(
- speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build();
+ // @formatter:off
+ graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).
+ method(method).
+ cancellable(this).
+ entryBCI(entryBCI).
+ speculationLog(speculationLog).
+ useProfilingInfo(useProfilingInfo).
+ compilationId(compilationId).build();
+ // @formatter:on
}
return graph;
}
@@ -219,7 +232,11 @@
return result;
}
- public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, boolean shouldRetainLocalVariables, CompilationIdentifier compilationId,
+ public CompilationResult compile(ResolvedJavaMethod method,
+ int entryBCI,
+ boolean useProfilingInfo,
+ boolean shouldRetainLocalVariables,
+ CompilationIdentifier compilationId,
DebugContext debug) {
StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, debug.getOptions(), debug);
CompilationResult result = new CompilationResult(compilationId);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Fri Jun 28 14:36:42 2019 +0530
@@ -129,8 +129,6 @@
*/
private AtomicReference<OptionValues> optionsRef = new AtomicReference<>();
- private final HotSpotGraalCompiler compiler;
-
private final DiagnosticsOutputDirectory outputDirectory;
private final Map<ExceptionAction, Integer> compilationProblemsPerAction;
@@ -161,7 +159,6 @@
CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
compilerConfigurationName = compilerConfigurationFactory.getName();
- compiler = new HotSpotGraalCompiler(jvmciRuntime, this, options);
if (IS_AOT) {
management = null;
} else {
@@ -367,7 +364,11 @@
}
private long runtimeStartTime;
- private boolean shutdown;
+
+ /**
+ * Called from compiler threads to check whether to bail out of a compilation.
+ */
+ private volatile boolean shutdown;
/**
* Take action related to entering a new execution phase.
@@ -394,6 +395,16 @@
BenchmarkCounters.shutdown(runtime(), optionsRef.get(), runtimeStartTime);
outputDirectory.close();
+
+ shutdownLibGraal();
+ }
+
+ /**
+ * Substituted by
+ * {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalRuntime}
+ * to call {@code org.graalvm.nativeimage.VMRuntime.shutdown()}.
+ */
+ private static void shutdownLibGraal() {
}
void clearMetrics() {
@@ -580,6 +591,7 @@
extra.put(DebugOptions.PrintGraphHost, host);
extra.put(DebugOptions.PrintGraphPort, port);
OptionValues compileOptions = new OptionValues(getOptions(), extra);
+ HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime().getCompiler();
compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false, compileOptions);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalServices.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotMetaData;
+
+public class HotSpotGraalServices {
+
+ /**
+ * Get the implicit exceptions section of a {@code HotSpotMetaData} if it exists.
+ */
+ @SuppressWarnings("unused")
+ public static byte[] getImplicitExceptionBytes(HotSpotMetaData metaData) {
+ return metaData.implicitExceptionBytes();
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java Fri Jun 28 14:36:42 2019 +0530
@@ -41,6 +41,7 @@
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin;
import org.graalvm.compiler.hotspot.word.HotSpotOperation;
+import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@@ -91,7 +92,7 @@
}
@Override
- public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) {
+ public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug, Cancellable cancellable) {
boolean useEncodedGraphs = UseEncodedGraphs.getValue(debug.getOptions());
if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements();
@@ -101,13 +102,13 @@
if (useEncodedGraphs) {
replacements.registerMethodSubstitution(msp, method, ROOT_COMPILATION, debug.getOptions());
}
- StructuredGraph methodSubstitution = replacements.getMethodSubstitution(msp, method, ROOT_COMPILATION, StructuredGraph.AllowAssumptions.YES, debug.getOptions());
+ StructuredGraph methodSubstitution = replacements.getMethodSubstitution(msp, method, ROOT_COMPILATION, StructuredGraph.AllowAssumptions.YES, cancellable, debug.getOptions());
methodSubstitution.resetDebug(debug);
return methodSubstitution;
}
return null;
}
- return super.getIntrinsicGraph(method, compilationId, debug);
+ return super.getIntrinsicGraph(method, compilationId, debug, cancellable);
}
@Override
@@ -122,7 +123,7 @@
}
// This assumes the normal path creates the graph using
// GraphBuilderConfiguration.getSnippetDefault with omits exception edges
- StructuredGraph subst = getMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, StructuredGraph.AllowAssumptions.NO, options);
+ StructuredGraph subst = getMethodSubstitution(msPlugin, targetMethod, INLINE_AFTER_PARSING, StructuredGraph.AllowAssumptions.NO, null, options);
return subst;
}
}
@@ -232,7 +233,7 @@
@Override
public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
- StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+ StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) {
boolean useEncodedGraphs = UseEncodedGraphs.getValue(options);
if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
if (!IS_IN_NATIVE_IMAGE) {
@@ -242,7 +243,7 @@
if (getEncodedSnippets() == null) {
throw GraalError.shouldNotReachHere("encoded snippets not found");
}
- return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this, context, allowAssumptions, options);
+ return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this, context, allowAssumptions, cancellable, options);
}
return null;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -39,7 +39,6 @@
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
-import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.GraalServices;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
@@ -60,7 +59,7 @@
@Override
public PrintStream getStream() {
- return Options.LogFile.getStream(defaultOptions());
+ return Options.LogFile.getStream();
}
/**
@@ -96,22 +95,57 @@
* operation is performed on the stream. This is required to break a deadlock in early JVMCI
* initialization.
*/
- static class DelayedOutputStream extends OutputStream {
+ class DelayedOutputStream extends OutputStream {
private volatile OutputStream lazy;
private OutputStream lazy() {
if (lazy == null) {
synchronized (this) {
if (lazy == null) {
+ String nameTemplate = LogStreamOptionKey.this.getValue(defaultOptions());
+ if (nameTemplate != null) {
+ String name = makeFilename(nameTemplate);
+ try {
+ final boolean enableAutoflush = true;
+ FileOutputStream result = new FileOutputStream(name);
+ if (!Services.IS_IN_NATIVE_IMAGE) {
+ printVMConfig(enableAutoflush, result);
+ } else {
+ // There are no VM arguments for the libgraal library.
+ }
+ lazy = result;
+ return lazy;
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("couldn't open file: " + name, e);
+ }
+ }
+
lazy = HotSpotJVMCIRuntime.runtime().getLogStream();
PrintStream ps = new PrintStream(lazy);
ps.printf("[Use -D%sLogFile=<path> to redirect Graal log output to a file.]%n", GRAAL_OPTION_PROPERTY_PREFIX);
+ ps.flush();
}
}
}
return lazy;
}
+ @SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "false positive on dead store to `ps`")
+ private void printVMConfig(final boolean enableAutoflush, FileOutputStream result) {
+ /*
+ * Add the JVM and Java arguments to the log file to help identity it.
+ */
+ PrintStream ps = new PrintStream(result, enableAutoflush);
+ List<String> inputArguments = GraalServices.getInputArguments();
+ if (inputArguments != null) {
+ ps.println("VM Arguments: " + String.join(" ", inputArguments));
+ }
+ String cmd = Services.getSavedProperties().get("sun.java.command");
+ if (cmd != null) {
+ ps.println("sun.java.command=" + cmd);
+ }
+ }
+
@Override
public void write(byte[] b, int off, int len) throws IOException {
lazy().write(b, off, len);
@@ -137,32 +171,8 @@
* Gets the print stream configured by this option. If no file is configured, the print
* stream will output to HotSpot's {@link HotSpotJVMCIRuntime#getLogStream() log} stream.
*/
- @SuppressFBWarnings(value = "DLS_DEAD_LOCAL_STORE", justification = "false positive on dead store to `ps`")
- public PrintStream getStream(OptionValues options) {
- String nameTemplate = getValue(options);
- if (nameTemplate != null) {
- String name = makeFilename(nameTemplate);
- try {
- final boolean enableAutoflush = true;
- PrintStream ps = new PrintStream(new FileOutputStream(name), enableAutoflush);
- /*
- * Add the JVM and Java arguments to the log file to help identity it.
- */
- List<String> inputArguments = GraalServices.getInputArguments();
- if (inputArguments != null) {
- ps.println("VM Arguments: " + String.join(" ", inputArguments));
- }
- String cmd = Services.getSavedProperties().get("sun.java.command");
- if (cmd != null) {
- ps.println("sun.java.command=" + cmd);
- }
- return ps;
- } catch (FileNotFoundException e) {
- throw new RuntimeException("couldn't open file: " + name, e);
- }
- } else {
- return new PrintStream(new DelayedOutputStream());
- }
+ public PrintStream getStream() {
+ return new PrintStream(new DelayedOutputStream());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Fri Jun 28 14:36:42 2019 +0530
@@ -41,9 +41,8 @@
*/
public final class JVMCIVersionCheck {
- // 0.57 introduces HotSpotJVMCIRuntime.excludeFromJVMCICompilation
- private static final int JVMCI8_MIN_MAJOR_VERSION = 0;
- private static final int JVMCI8_MIN_MINOR_VERSION = 57;
+ private static final int JVMCI8_MIN_MAJOR_VERSION = 19;
+ private static final int JVMCI8_MIN_MINOR_VERSION = 1;
private static void failVersionCheck(Map<String, String> props, boolean exit, String reason, Object... args) {
Formatter errorMessage = new Formatter().format(reason, args);
@@ -55,7 +54,7 @@
errorMessage.format("Currently used VM configuration is: %s%n", vmName);
if (props.get("java.specification.version").compareTo("1.9") < 0) {
errorMessage.format("Download the latest JVMCI JDK 8 from " +
- "http://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/index.html or " +
+ "https://www.oracle.com/technetwork/graalvm/downloads/index.html or " +
"https://github.com/graalvm/openjdk8-jvmci-builder/releases");
} else {
errorMessage.format("Download JDK 11 or later.");
@@ -156,6 +155,14 @@
return false;
}
+ private static String getJVMCIVersionString(int major, int minor) {
+ if (major >= 19) {
+ return String.format("%d-b%02d", major, minor);
+ } else {
+ return String.format("%d.%d", major, minor);
+ }
+ }
+
private void run(boolean exitOnFailure, int jvmci8MinMajorVersion, int jvmci8MinMinorVersion) {
// Don't use regular expressions to minimize Graal startup time
if (javaSpecVersion.compareTo("1.9") < 0) {
@@ -180,8 +187,8 @@
if (major > jvmci8MinMajorVersion || (major >= jvmci8MinMajorVersion && minor >= jvmci8MinMinorVersion)) {
return;
}
- failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %d.%d < %d.%d.%n",
- major, minor, jvmci8MinMajorVersion, jvmci8MinMinorVersion);
+ failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n",
+ getJVMCIVersionString(major, minor), getJVMCIVersionString(jvmci8MinMajorVersion, jvmci8MinMinorVersion));
return;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,6 +66,7 @@
import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.nodeinfo.Verbosity;
import org.graalvm.compiler.nodes.CallTargetNode;
+import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.EncodedGraph;
import org.graalvm.compiler.nodes.FrameState;
@@ -109,7 +110,6 @@
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MemoryAccessProvider;
import jdk.vm.ci.meta.MethodHandleAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
@@ -283,24 +283,30 @@
}
StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements, IntrinsicContext.CompilationContext context,
- StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+ StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) {
Integer startOffset = snippetStartOffsets.get(plugin.toString() + context);
if (startOffset == null) {
throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin + " with " + context);
}
ResolvedJavaType accessingClass = replacements.getProviders().getMetaAccess().lookupJavaType(plugin.getDeclaringClass());
- return decodeGraph(original, accessingClass, startOffset, replacements, context, allowAssumptions, options);
+ return decodeGraph(original, accessingClass, startOffset, replacements, context, allowAssumptions, cancellable, options);
}
@SuppressWarnings("try")
- private StructuredGraph decodeGraph(ResolvedJavaMethod method, ResolvedJavaType accessingClass, int startOffset, ReplacementsImpl replacements,
- IntrinsicContext.CompilationContext context, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+ private StructuredGraph decodeGraph(ResolvedJavaMethod method,
+ ResolvedJavaType accessingClass,
+ int startOffset,
+ ReplacementsImpl replacements,
+ IntrinsicContext.CompilationContext context,
+ StructuredGraph.AllowAssumptions allowAssumptions,
+ Cancellable cancellable,
+ OptionValues options) {
Providers providers = replacements.getProviders();
EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses,
methodKey(method), accessingClass, method.getDeclaringClass());
try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) {
- StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).method(method).setIsSubstitution(true).build();
+ StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).cancellable(cancellable).method(method).setIsSubstitution(true).build();
PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, method, context, encodedGraph);
graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition());
@@ -432,7 +438,7 @@
originalProvider.getConstantReflection());
HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection,
originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(),
- originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins());
+ originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(), originalProvider.getGC());
HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection,
originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget());
filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins());
@@ -1048,7 +1054,7 @@
}
@Override
- protected boolean tryInvocationPlugin(CallTargetNode.InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
+ protected boolean tryInvocationPlugin(CallTargetNode.InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
return false;
}
@@ -1056,7 +1062,7 @@
// Always defer Fold until decode time but NodeIntrinsics may fold if they are able.
return false;
}
- return super.tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType);
+ return super.tryInvocationPlugin(invokeKind, args, targetMethod, resultType);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java Fri Jun 28 14:36:42 2019 +0530
@@ -38,6 +38,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
+import org.graalvm.compiler.core.GraalServiceThread;
import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.debug.CSVUtil;
import org.graalvm.compiler.debug.GraalError;
@@ -445,7 +446,7 @@
enabled = true;
}
if (Options.TimedDynamicCounters.getValue(options) > 0) {
- Thread thread = new Thread() {
+ Thread thread = new GraalServiceThread(new Runnable() {
long lastTime = System.nanoTime();
@Override
@@ -462,7 +463,7 @@
}
}
}
- };
+ });
thread.setDaemon(true);
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1ArrayRangePostWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-
-package org.graalvm.compiler.hotspot.gc.g1;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.gc.shared.ArrayRangeWriteBarrier;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
-public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier {
- public static final NodeClass<G1ArrayRangePostWriteBarrier> TYPE = NodeClass.create(G1ArrayRangePostWriteBarrier.class);
-
- public G1ArrayRangePostWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
- super(TYPE, address, length, elementStride);
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1ArrayRangePreWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-
-package org.graalvm.compiler.hotspot.gc.g1;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.gc.shared.ArrayRangeWriteBarrier;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
-public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
- public static final NodeClass<G1ArrayRangePreWriteBarrier> TYPE = NodeClass.create(G1ArrayRangePreWriteBarrier.class);
-
- public G1ArrayRangePreWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
- super(TYPE, address, length, elementStride);
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1BarrierSet.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2019, Red Hat Inc. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 org.graalvm.compiler.hotspot.gc.g1;
-
-import org.graalvm.compiler.debug.GraalError;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.gc.shared.BarrierSet;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
-import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
-import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
-import org.graalvm.compiler.nodes.memory.FixedAccessNode;
-import org.graalvm.compiler.nodes.memory.HeapAccess;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.nodes.memory.WriteNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.compiler.nodes.type.StampTool;
-
-public class G1BarrierSet extends BarrierSet {
-
- public G1BarrierSet(GraalHotSpotVMConfig vmConfig) {
- super(vmConfig);
- }
-
- @Override
- public void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
- if (node.getBarrierType() == HeapAccess.BarrierType.WEAK_FIELD) {
- G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.getAddress(), node, false));
- graph.addAfterFixed(node, barrier);
- }
- }
-
- @Override
- public void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
- HeapAccess.BarrierType barrierType = node.getBarrierType();
- switch (barrierType) {
- case NONE:
- // nothing to do
- break;
- case FIELD:
- case ARRAY:
- case UNKNOWN:
- boolean init = node.getLocationIdentity().isInit();
- if (!init || !getVMConfig().useDeferredInitBarriers) {
- if (!init) {
- // The pre barrier does nothing if the value being read is null, so it can
- // be explicitly skipped when this is an initializing store.
- addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
- }
- boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
- addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
- }
- break;
- default:
- throw new GraalError("unexpected barrier type: " + barrierType);
- }
- }
-
- @Override
- public void addAtomicReadWriteNodeBarriers(LoweredAtomicReadAndWriteNode node, StructuredGraph graph) {
- HeapAccess.BarrierType barrierType = node.getBarrierType();
- switch (barrierType) {
- case NONE:
- // nothing to do
- break;
- case FIELD:
- case ARRAY:
- case UNKNOWN:
- boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
- addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
- addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
- break;
- default:
- throw new GraalError("unexpected barrier type: " + barrierType);
- }
- }
-
- @Override
- public void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph) {
- HeapAccess.BarrierType barrierType = node.getBarrierType();
- switch (barrierType) {
- case NONE:
- // nothing to do
- break;
- case FIELD:
- case ARRAY:
- case UNKNOWN:
- boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
- addG1PreWriteBarrier(node, node.getAddress(), node.getExpectedValue(), false, false, graph);
- addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
- break;
- default:
- throw new GraalError("unexpected barrier type: " + barrierType);
- }
- }
-
- @Override
- public void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph) {
- if (!write.isInitialization()) {
- // The pre barrier does nothing if the value being read is null, so it can
- // be explicitly skipped when this is an initializing store.
- G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
- graph.addBeforeFixed(write.asNode(), g1ArrayRangePreWriteBarrier);
- }
- G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
- graph.addAfterFixed(write.asNode(), g1ArrayRangePostWriteBarrier);
- }
-
- private static void addG1PreWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
- G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(address, value, doLoad, nullCheck));
- preBarrier.setStateBefore(node.stateBefore());
- node.setNullCheck(false);
- node.setStateBefore(null);
- graph.addBeforeFixed(node, preBarrier);
- }
-
- private static void addG1PostWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean precise, StructuredGraph graph) {
- final boolean alwaysNull = StampTool.isPointerAlwaysNull(value);
- graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(address, value, precise, alwaysNull)));
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1PostWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.gc.g1;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.gc.shared.ObjectWriteBarrier;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
-public class G1PostWriteBarrier extends ObjectWriteBarrier {
-
- public static final NodeClass<G1PostWriteBarrier> TYPE = NodeClass.create(G1PostWriteBarrier.class);
- protected final boolean alwaysNull;
-
- public G1PostWriteBarrier(AddressNode address, ValueNode value, boolean precise, boolean alwaysNull) {
- this(TYPE, address, value, precise, alwaysNull);
- }
-
- private G1PostWriteBarrier(NodeClass<? extends G1PostWriteBarrier> c, AddressNode address, ValueNode value, boolean precise, boolean alwaysNull) {
- super(c, address, value, precise);
- this.alwaysNull = alwaysNull;
- }
-
- public boolean alwaysNull() {
- return alwaysNull;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1PreWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-
-package org.graalvm.compiler.hotspot.gc.g1;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.gc.shared.ObjectWriteBarrier;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.DeoptimizingNode;
-import org.graalvm.compiler.nodes.FrameState;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
-public final class G1PreWriteBarrier extends ObjectWriteBarrier implements DeoptimizingNode.DeoptBefore {
-
- public static final NodeClass<G1PreWriteBarrier> TYPE = NodeClass.create(G1PreWriteBarrier.class);
-
- @OptionalInput(InputType.State) private FrameState stateBefore;
- private final boolean nullCheck;
- private final boolean doLoad;
-
- public G1PreWriteBarrier(AddressNode address, ValueNode expectedObject, boolean doLoad, boolean nullCheck) {
- super(TYPE, address, expectedObject, true);
- this.doLoad = doLoad;
- this.nullCheck = nullCheck;
- }
-
- public ValueNode getExpectedObject() {
- return getValue();
- }
-
- public boolean doLoad() {
- return doLoad;
- }
-
- public boolean getNullCheck() {
- return nullCheck;
- }
-
- @Override
- public boolean canDeoptimize() {
- return nullCheck;
- }
-
- @Override
- public FrameState stateBefore() {
- return stateBefore;
- }
-
- @Override
- public void setStateBefore(FrameState state) {
- updateUsages(stateBefore, state);
- stateBefore = state;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1ReferentFieldReadBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.gc.g1;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.gc.shared.ObjectWriteBarrier;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-/**
- * The {@code G1ReferentFieldReadBarrier} is added when a read access is performed to the referent
- * field of a {@link java.lang.ref.Reference} object (through a {@code LoadFieldNode} or an
- * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the
- * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled.
- */
-@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
-public final class G1ReferentFieldReadBarrier extends ObjectWriteBarrier {
- public static final NodeClass<G1ReferentFieldReadBarrier> TYPE = NodeClass.create(G1ReferentFieldReadBarrier.class);
-
- private final boolean doLoad;
-
- public G1ReferentFieldReadBarrier(AddressNode address, ValueNode expectedObject, boolean doLoad) {
- super(TYPE, address, expectedObject, true);
- this.doLoad = doLoad;
- }
-
- public ValueNode getExpectedObject() {
- return getValue();
- }
-
- public boolean doLoad() {
- return doLoad;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/ArrayRangeWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.gc.shared;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.nodes.WriteBarrier;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.compiler.nodes.spi.Lowerable;
-
-@NodeInfo
-public abstract class ArrayRangeWriteBarrier extends WriteBarrier implements Lowerable {
-
- public static final NodeClass<ArrayRangeWriteBarrier> TYPE = NodeClass.create(ArrayRangeWriteBarrier.class);
- @Input(InputType.Association) AddressNode address;
- @Input ValueNode length;
-
- private final int elementStride;
-
- protected ArrayRangeWriteBarrier(NodeClass<? extends ArrayRangeWriteBarrier> c, AddressNode address, ValueNode length, int elementStride) {
- super(c);
- this.address = address;
- this.length = length;
- this.elementStride = elementStride;
- }
-
- public AddressNode getAddress() {
- return address;
- }
-
- public ValueNode getLength() {
- return length;
- }
-
- public int getElementStride() {
- return elementStride;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/BarrierSet.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2019, Red Hat Inc. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 org.graalvm.compiler.hotspot.gc.shared;
-
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
-import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
-import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.nodes.memory.WriteNode;
-
-public abstract class BarrierSet {
- private final GraalHotSpotVMConfig vmConfig;
-
- protected BarrierSet(GraalHotSpotVMConfig vmConfig) {
- this.vmConfig = vmConfig;
- }
-
- public final GraalHotSpotVMConfig getVMConfig() {
- return vmConfig;
- }
-
- public abstract void addReadNodeBarriers(ReadNode node, StructuredGraph graph);
-
- public abstract void addWriteNodeBarriers(WriteNode node, StructuredGraph graph);
-
- public abstract void addAtomicReadWriteNodeBarriers(LoweredAtomicReadAndWriteNode node, StructuredGraph graph);
-
- public abstract void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph);
-
- public abstract void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/CardTableBarrierSet.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2019, Red Hat Inc. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 org.graalvm.compiler.hotspot.gc.shared;
-
-import org.graalvm.compiler.debug.GraalError;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
-import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
-import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
-import org.graalvm.compiler.nodes.memory.FixedAccessNode;
-import org.graalvm.compiler.nodes.memory.HeapAccess;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.nodes.memory.WriteNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.compiler.nodes.type.StampTool;
-
-public class CardTableBarrierSet extends BarrierSet {
-
- public CardTableBarrierSet(GraalHotSpotVMConfig vmConfig) {
- super(vmConfig);
- }
-
- @Override
- public void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
- // Nothing to do here.
- }
-
- @Override
- public void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) {
- HeapAccess.BarrierType barrierType = node.getBarrierType();
- switch (barrierType) {
- case NONE:
- // nothing to do
- break;
- case FIELD:
- case ARRAY:
- case UNKNOWN:
- boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
- boolean init = node.getLocationIdentity().isInit();
- if (!init || !getVMConfig().useDeferredInitBarriers) {
- addSerialPostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
- }
- break;
- default:
- throw new GraalError("unexpected barrier type: " + barrierType);
- }
- }
-
- @Override
- public void addAtomicReadWriteNodeBarriers(LoweredAtomicReadAndWriteNode node, StructuredGraph graph) {
- HeapAccess.BarrierType barrierType = node.getBarrierType();
- switch (barrierType) {
- case NONE:
- // nothing to do
- break;
- case FIELD:
- case ARRAY:
- case UNKNOWN:
- boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
- addSerialPostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
- break;
- default:
- throw new GraalError("unexpected barrier type: " + barrierType);
- }
- }
-
- @Override
- public void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph) {
- HeapAccess.BarrierType barrierType = node.getBarrierType();
- switch (barrierType) {
- case NONE:
- // nothing to do
- break;
- case FIELD:
- case ARRAY:
- case UNKNOWN:
- boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
- addSerialPostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
- break;
- default:
- throw new GraalError("unexpected barrier type: " + barrierType);
- }
- }
-
- @Override
- public void addArrayRangeBarriers(ArrayRangeWrite write, StructuredGraph graph) {
- SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
- graph.addAfterFixed(write.asNode(), serialArrayRangeWriteBarrier);
- }
-
- protected void addSerialPostWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean precise, StructuredGraph graph) {
- final boolean alwaysNull = StampTool.isPointerAlwaysNull(value);
- if (alwaysNull) {
- // Serial barrier isn't needed for null value
- return;
- }
- graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(address, precise)));
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/ObjectWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.gc.shared;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.nodes.WriteBarrier;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-@NodeInfo
-public abstract class ObjectWriteBarrier extends WriteBarrier {
-
- public static final NodeClass<ObjectWriteBarrier> TYPE = NodeClass.create(ObjectWriteBarrier.class);
- @Input(InputType.Association) protected AddressNode address;
- @OptionalInput protected ValueNode value;
- protected final boolean precise;
-
- protected ObjectWriteBarrier(NodeClass<? extends ObjectWriteBarrier> c, AddressNode address, ValueNode value, boolean precise) {
- super(c);
- this.address = address;
- this.value = value;
- this.precise = precise;
- }
-
- public ValueNode getValue() {
- return value;
- }
-
- public AddressNode getAddress() {
- return address;
- }
-
- public boolean usePrecise() {
- return precise;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/SerialArrayRangeWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.gc.shared;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-@NodeInfo(cycles = CYCLES_8, size = SIZE_8)
-public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier {
- public static final NodeClass<SerialArrayRangeWriteBarrier> TYPE = NodeClass.create(SerialArrayRangeWriteBarrier.class);
-
- public SerialArrayRangeWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
- super(TYPE, address, length, elementStride);
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/SerialWriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.gc.shared;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-
-@NodeInfo(cycles = CYCLES_8, size = SIZE_4)
-public class SerialWriteBarrier extends ObjectWriteBarrier {
-
- public static final NodeClass<SerialWriteBarrier> TYPE = NodeClass.create(SerialWriteBarrier.class);
-
- public SerialWriteBarrier(AddressNode address, boolean precise) {
- this(TYPE, address, precise);
- }
-
- protected SerialWriteBarrier(NodeClass<? extends SerialWriteBarrier> c, AddressNode address, boolean precise) {
- super(c, address, null, precise);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,8 +32,8 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.Phase;
-import org.graalvm.compiler.phases.common.ExpandLogicPhase;
-import org.graalvm.compiler.phases.common.FixReadsPhase;
+import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.tiers.LowTierContext;
import org.graalvm.compiler.phases.tiers.Suites;
import org.graalvm.compiler.phases.tiers.SuitesCreator;
@@ -55,10 +55,11 @@
public Suites createSuites(OptionValues options) {
Suites suites = super.createSuites(options);
- ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class);
+ ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(UseTrappingNullChecksPhase.class);
if (findPhase == null) {
- findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class);
+ findPhase = suites.getLowTier().findPhase(SchedulePhase.class);
}
+ findPhase.previous();
findPhase.add(addressLowering);
return suites;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,7 +26,6 @@
import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs;
-import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs;
import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace;
import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
@@ -60,13 +59,6 @@
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
-import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePreWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1ReferentFieldReadBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialArrayRangeWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
import org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode;
import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode;
import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode;
@@ -82,6 +74,8 @@
import org.graalvm.compiler.hotspot.replacements.AssertionSnippets;
import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode;
import org.graalvm.compiler.hotspot.replacements.HashCodeSnippets;
+import org.graalvm.compiler.hotspot.replacements.HotSpotG1WriteBarrierSnippets;
+import org.graalvm.compiler.hotspot.replacements.HotSpotSerialWriteBarrierSnippets;
import org.graalvm.compiler.hotspot.replacements.HubGetClassNode;
import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode;
import org.graalvm.compiler.hotspot.replacements.InstanceOfSnippets;
@@ -92,7 +86,6 @@
import org.graalvm.compiler.hotspot.replacements.ObjectCloneSnippets;
import org.graalvm.compiler.hotspot.replacements.StringToBytesSnippets;
import org.graalvm.compiler.hotspot.replacements.UnsafeLoadSnippets;
-import org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets;
import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets;
import org.graalvm.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets;
import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets;
@@ -135,6 +128,13 @@
import org.graalvm.compiler.nodes.extended.OSRStartNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.nodes.extended.StoreHubNode;
+import org.graalvm.compiler.nodes.gc.G1ArrayRangePostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ArrayRangePreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ReferentFieldReadBarrier;
+import org.graalvm.compiler.nodes.gc.SerialArrayRangeWriteBarrier;
+import org.graalvm.compiler.nodes.gc.SerialWriteBarrier;
import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode;
import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
@@ -191,7 +191,8 @@
protected InstanceOfSnippets.Templates instanceofSnippets;
protected NewObjectSnippets.Templates newObjectSnippets;
protected MonitorSnippets.Templates monitorSnippets;
- protected WriteBarrierSnippets.Templates writeBarrierSnippets;
+ protected HotSpotSerialWriteBarrierSnippets.Templates serialWriteBarrierSnippets;
+ protected HotSpotG1WriteBarrierSnippets.Templates g1WriteBarrierSnippets;
protected LoadExceptionObjectSnippets.Templates exceptionObjectSnippets;
protected UnsafeLoadSnippets.Templates unsafeLoadSnippets;
protected AssertionSnippets.Templates assertionSnippets;
@@ -220,7 +221,8 @@
instanceofSnippets = new InstanceOfSnippets.Templates(options, factories, runtime, providers, target);
newObjectSnippets = new NewObjectSnippets.Templates(options, factories, runtime, providers, target, config);
monitorSnippets = new MonitorSnippets.Templates(options, factories, runtime, providers, target, config.useFastLocking);
- writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config);
+ g1WriteBarrierSnippets = new HotSpotG1WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config);
+ serialWriteBarrierSnippets = new HotSpotSerialWriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config);
exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, factories, providers, target);
unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, factories, providers, target);
assertionSnippets = new AssertionSnippets.Templates(options, factories, providers, target);
@@ -228,11 +230,14 @@
stringToBytesSnippets = new StringToBytesSnippets.Templates(options, factories, providers, target);
hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target);
resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target);
- if (!JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options)) {
+ objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target);
+ foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target);
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
+ // AOT only introduced in JDK 9
+ profileSnippets = null;
+ } else {
profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target);
}
- objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target);
- foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target);
}
public ArrayCopySnippets.Templates getArraycopySnippets() {
@@ -340,19 +345,19 @@
} else if (n instanceof ArrayCopyWithDelayedLoweringNode) {
arraycopySnippets.lower((ArrayCopyWithDelayedLoweringNode) n, tool);
} else if (n instanceof G1PreWriteBarrier) {
- writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool);
+ g1WriteBarrierSnippets.lower((G1PreWriteBarrier) n, tool);
} else if (n instanceof G1PostWriteBarrier) {
- writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool);
+ g1WriteBarrierSnippets.lower((G1PostWriteBarrier) n, tool);
} else if (n instanceof G1ReferentFieldReadBarrier) {
- writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool);
+ g1WriteBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, tool);
} else if (n instanceof SerialWriteBarrier) {
- writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
+ serialWriteBarrierSnippets.lower((SerialWriteBarrier) n, tool);
} else if (n instanceof SerialArrayRangeWriteBarrier) {
- writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
+ serialWriteBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
} else if (n instanceof G1ArrayRangePreWriteBarrier) {
- writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool);
+ g1WriteBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, tool);
} else if (n instanceof G1ArrayRangePostWriteBarrier) {
- writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool);
+ g1WriteBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool);
} else if (n instanceof NewMultiArrayNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((NewMultiArrayNode) n, tool);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGCProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.meta;
+
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.gc.BarrierSet;
+import org.graalvm.compiler.nodes.gc.CardTableBarrierSet;
+import org.graalvm.compiler.nodes.gc.G1BarrierSet;
+import org.graalvm.compiler.nodes.java.AbstractNewObjectNode;
+import org.graalvm.compiler.nodes.memory.FixedAccessNode;
+import org.graalvm.compiler.nodes.spi.GCProvider;
+
+public class HotSpotGCProvider implements GCProvider {
+ private final BarrierSet barrierSet;
+
+ public HotSpotGCProvider(GraalHotSpotVMConfig config) {
+ this.barrierSet = createBarrierSet(config);
+ }
+
+ @Override
+ public BarrierSet getBarrierSet() {
+ return barrierSet;
+ }
+
+ private BarrierSet createBarrierSet(GraalHotSpotVMConfig config) {
+ boolean useDeferredInitBarriers = config.useDeferredInitBarriers;
+ if (config.useG1GC) {
+ return new G1BarrierSet() {
+ @Override
+ protected boolean writeRequiresPostBarrier(FixedAccessNode initializingWrite, ValueNode writtenValue) {
+ if (!super.writeRequiresPostBarrier(initializingWrite, writtenValue)) {
+ return false;
+ }
+ return !useDeferredInitBarriers || !isWriteToNewObject(initializingWrite);
+ }
+ };
+ } else {
+ return new CardTableBarrierSet() {
+ @Override
+ protected boolean writeRequiresBarrier(FixedAccessNode initializingWrite, ValueNode writtenValue) {
+ if (!super.writeRequiresBarrier(initializingWrite, writtenValue)) {
+ return false;
+ }
+ return !useDeferredInitBarriers || !isWriteToNewObject(initializingWrite);
+ }
+ };
+ }
+ }
+
+ /**
+ * For initializing writes, the last allocation executed by the JVM is guaranteed to be
+ * automatically card marked so it's safe to skip the card mark in the emitted code.
+ */
+ protected boolean isWriteToNewObject(FixedAccessNode initializingWrite) {
+ if (!initializingWrite.getLocationIdentity().isInit()) {
+ return false;
+ }
+ // This is only allowed for the last allocation in sequence
+ ValueNode base = initializingWrite.getAddress().getBase();
+ if (base instanceof AbstractNewObjectNode) {
+ Node pred = initializingWrite.predecessor();
+ while (pred != null) {
+ if (pred == base) {
+ return true;
+ }
+ if (pred instanceof AbstractNewObjectNode) {
+ initializingWrite.getDebug().log(DebugContext.INFO_LEVEL, "Disallowed deferred init because %s was last allocation instead of %s", pred, base);
+ return false;
+ }
+ pred = pred.predecessor();
+ }
+ }
+ initializingWrite.getDebug().log(DebugContext.INFO_LEVEL, "Unable to find allocation for deferred init for %s with base %s", initializingWrite, base);
+ return false;
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,7 +30,6 @@
import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION;
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MutableCallSite;
@@ -101,6 +100,7 @@
import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins;
import org.graalvm.compiler.replacements.arraycopy.ArrayCopyNode;
import org.graalvm.compiler.serviceprovider.GraalServices;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.WordOperationPlugin;
import org.graalvm.compiler.word.WordTypes;
import jdk.internal.vm.compiler.word.LocationIdentity;
@@ -278,7 +278,7 @@
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementBytecodeProvider) {
Registration r;
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
r = new Registration(plugins, Unsafe.class, replacementBytecodeProvider);
} else {
r = new Registration(plugins, "jdk.internal.misc.Unsafe", replacementBytecodeProvider);
@@ -403,7 +403,7 @@
}
private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) {
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", bytecodeProvider);
utf16r.registerMethodSubstitution(StringUTF16Substitutions.class, "toBytes", char[].class, int.class, int.class);
utf16r.registerMethodSubstitution(StringUTF16Substitutions.class, "getChars", byte[].class, int.class, int.class, char[].class, int.class);
@@ -437,7 +437,7 @@
public static final String constantPoolClass;
static {
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
cbcEncryptName = "encrypt";
cbcDecryptName = "decrypt";
aesEncryptName = "encryptBlock";
@@ -476,7 +476,7 @@
Registration r = new Registration(plugins, BigInteger.class, bytecodeProvider);
if (config.useMultiplyToLenIntrinsic()) {
assert config.multiplyToLen != 0L;
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
r.registerMethodSubstitution(BigIntegerSubstitutions.class, "multiplyToLen", "multiplyToLenStatic", int[].class, int.class, int[].class, int.class,
int[].class);
} else {
@@ -503,7 +503,7 @@
boolean useSha256 = config.useSHA256Intrinsics();
boolean useSha512 = config.useSHA512Intrinsics();
- if (!Java8OrEarlier && (useSha1 || useSha256 || useSha512)) {
+ if (JavaVersionUtil.JAVA_SPEC > 8 && (useSha1 || useSha256 || useSha512)) {
Registration r = new Registration(plugins, "sun.security.provider.DigestBase", bytecodeProvider);
r.registerMethodSubstitution(DigestBaseSubstitutions.class, "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class);
}
@@ -602,7 +602,7 @@
if (config.useCRC32Intrinsics) {
Registration r = new Registration(plugins, CRC32.class, bytecodeProvider);
r.registerMethodSubstitution(CRC32Substitutions.class, "update", int.class, int.class);
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
r.registerMethodSubstitution(CRC32Substitutions.class, "updateBytes", int.class, byte[].class, int.class, int.class);
r.registerMethodSubstitution(CRC32Substitutions.class, "updateByteBuffer", int.class, long.class, int.class, int.class);
} else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -81,24 +81,24 @@
import static org.graalvm.compiler.hotspot.HotSpotHostBackend.THROW_DELAYED_STACKOVERFLOW_ERROR;
import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
import static org.graalvm.compiler.hotspot.replacements.AssertionSnippets.ASSERTION_VM_MESSAGE_C;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotG1WriteBarrierSnippets.G1WBPOSTCALL;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotG1WriteBarrierSnippets.G1WBPRECALL;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotG1WriteBarrierSnippets.VALIDATE_OBJECT;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_END_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.TLAB_TOP_LOCATION;
+import static org.graalvm.compiler.hotspot.replacements.Log.LOG_OBJECT;
+import static org.graalvm.compiler.hotspot.replacements.Log.LOG_PRIMITIVE;
+import static org.graalvm.compiler.hotspot.replacements.Log.LOG_PRINTF;
import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITORENTER;
import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITOREXIT;
import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_INSTANCE;
import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_INSTANCE_OR_NULL;
import static org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions.THREAD_IS_INTERRUPTED;
-import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPOSTCALL;
-import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPRECALL;
-import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.VALIDATE_OBJECT;
import static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.EXCEPTION_HANDLER_FOR_PC;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.VM_MESSAGE_C;
import static org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub.EXCEPTION_HANDLER_FOR_RETURN_ADDRESS;
import static org.graalvm.compiler.nodes.java.ForeignCallDescriptors.REGISTER_FINALIZER;
-import static org.graalvm.compiler.replacements.Log.LOG_OBJECT;
-import static org.graalvm.compiler.replacements.Log.LOG_PRIMITIVE;
-import static org.graalvm.compiler.replacements.Log.LOG_PRINTF;
import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java Fri Jun 28 14:36:42 2019 +0530
@@ -50,17 +50,18 @@
private final SnippetReflectionProvider snippetReflection;
private final HotSpotWordTypes wordTypes;
private final Plugins graphBuilderPlugins;
+ private final HotSpotGCProvider gc;
public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField,
- HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, SuitesProvider suites,
- HotSpotRegistersProvider registers,
- SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins) {
- super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider());
+ HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, SuitesProvider suites, HotSpotRegistersProvider registers,
+ SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins, HotSpotGCProvider gc) {
+ super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), gc);
this.suites = suites;
this.registers = registers;
this.snippetReflection = snippetReflection;
this.wordTypes = wordTypes;
this.graphBuilderPlugins = graphBuilderPlugins;
+ this.gc = gc;
}
@Override
@@ -94,51 +95,54 @@
}
@Override
+ public HotSpotGCProvider getGC() {
+ return gc;
+ }
+
+ @Override
public Providers copyWith(MetaAccessProvider substitution) {
return new HotSpotProviders(substitution, getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+ getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getGC());
}
@Override
public Providers copyWith(CodeCacheProvider substitution) {
return new HotSpotProviders(getMetaAccess(), (HotSpotCodeCacheProvider) substitution, getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(),
- getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+ getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getGC());
}
@Override
public Providers copyWith(ConstantReflectionProvider substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+ getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getGC());
}
@Override
public Providers copyWith(ConstantFieldProvider substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+ getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getGC());
}
@Override
public Providers copyWith(ForeignCallsProvider substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), (HotSpotForeignCallsProvider) substitution, getLowerer(), getReplacements(),
- getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+ getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getGC());
}
@Override
public Providers copyWith(LoweringProvider substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), substitution, getReplacements(), getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+ getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getGC());
}
@Override
public Providers copyWith(Replacements substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins());
+ getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getGC());
}
public Providers copyWith(Plugins substitution) {
return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(),
- getRegisters(), getSnippetReflection(), getWordTypes(), substitution);
+ getRegisters(), getSnippetReflection(), getWordTypes(), substitution, getGC());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -39,8 +39,6 @@
import org.graalvm.compiler.hotspot.lir.VerifyMaxRegisterSizePhase;
import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase;
import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase;
-import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
-import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
import org.graalvm.compiler.hotspot.phases.aot.AOTInliningPolicy;
import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase;
import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase;
@@ -112,11 +110,6 @@
}
}
- ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config));
- if (VerifyPhases.getValue(options)) {
- ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config));
- }
-
return ret;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotUnsafeSubstitutions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotUnsafeSubstitutions.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,19 +24,18 @@
package org.graalvm.compiler.hotspot.meta;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
-
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.hotspot.HotSpotBackend;
import org.graalvm.compiler.nodes.ComputeObjectAddressNode;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.WordFactory;
@ClassSubstitution(className = {"jdk.internal.misc.Unsafe", "sun.misc.Unsafe"})
public class HotSpotUnsafeSubstitutions {
- public static final String copyMemoryName = Java8OrEarlier ? "copyMemory" : "copyMemory0";
+ public static final String copyMemoryName = JavaVersionUtil.JAVA_SPEC <= 8 ? "copyMemory" : "copyMemory0";
@SuppressWarnings("unused")
@MethodSubstitution(isStatic = false)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/AllocaNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/AllocaNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,8 +27,6 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
-import java.util.BitSet;
-
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.lir.VirtualStackSlot;
@@ -39,7 +37,6 @@
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
-import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
/**
@@ -55,26 +52,14 @@
*/
protected final int slots;
- /**
- * The indexes of the object pointer slots in the block. Each such object pointer slot must be
- * initialized before any safepoint in the method otherwise the garbage collector will see
- * garbage values when processing these slots.
- */
- protected final BitSet objects;
-
public AllocaNode(@InjectedNodeParameter WordTypes wordTypes, int slots) {
- this(slots, wordTypes.getWordKind(), new BitSet());
- }
-
- public AllocaNode(int slots, JavaKind wordKind, BitSet objects) {
- super(TYPE, StampFactory.forKind(wordKind));
+ super(TYPE, StampFactory.forKind(wordTypes.getWordKind()));
this.slots = slots;
- this.objects = objects;
}
@Override
public void generate(NodeLIRBuilderTool gen) {
- VirtualStackSlot array = gen.getLIRGeneratorTool().allocateStackSlots(slots, objects, null);
+ VirtualStackSlot array = gen.getLIRGeneratorTool().allocateStackSlots(slots);
Value result = gen.getLIRGeneratorTool().emitAddress(array);
gen.setResult(this, result);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,8 +28,6 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
-import java.util.BitSet;
-
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.lir.VirtualStackSlot;
@@ -64,7 +62,7 @@
int size = rank * 4;
int wordSize = lirGen.target().wordSize;
int slots = roundUp(size, wordSize) / wordSize;
- VirtualStackSlot array = lirGen.allocateStackSlots(slots, new BitSet(0), null);
+ VirtualStackSlot array = lirGen.allocateStackSlots(slots);
Value result = lirGen.emitAddress(array);
gen.setResult(this, result);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/MonitorCounterNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/MonitorCounterNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,8 +26,6 @@
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
-import java.util.BitSet;
-
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
@@ -56,7 +54,7 @@
@Override
public void generate(NodeLIRBuilderTool gen) {
assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance";
- VirtualStackSlot counter = gen.getLIRGeneratorTool().getResult().getFrameMapBuilder().allocateStackSlots(1, new BitSet(0), null);
+ VirtualStackSlot counter = gen.getLIRGeneratorTool().getResult().getFrameMapBuilder().allocateStackSlots(1);
Value result = gen.getLIRGeneratorTool().emitAddress(counter);
gen.setResult(this, result);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/VMErrorNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/VMErrorNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -38,7 +38,6 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.compiler.replacements.Log;
import org.graalvm.compiler.replacements.nodes.CStringConstant;
import jdk.vm.ci.code.CodeUtil;
@@ -46,8 +45,8 @@
import jdk.vm.ci.meta.Value;
/**
- * Causes the VM to exit with a description of the current Java location and an optional
- * {@linkplain Log#printf(String, long) formatted} error message specified.
+ * Causes the VM to exit with a description of the current Java location and an optional printf
+ * formatted error message specified.
*/
@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN)
public final class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/WriteBarrier.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.nodes;
-
-import org.graalvm.compiler.core.common.type.StampFactory;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.FixedWithNextNode;
-import org.graalvm.compiler.nodes.spi.Lowerable;
-import org.graalvm.compiler.nodes.spi.LoweringTool;
-
-@NodeInfo
-public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable {
-
- public static final NodeClass<WriteBarrier> TYPE = NodeClass.create(WriteBarrier.class);
-
- protected WriteBarrier(NodeClass<? extends WriteBarrier> c) {
- super(c, StampFactory.forVoid());
- }
-
- @Override
- public void lower(LoweringTool tool) {
- assert graph().getGuardsStage().areFrameStatesAtDeopts();
- tool.getLowerer().lower(this, tool);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,6 @@
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
import jdk.vm.ci.meta.Constant;
@@ -84,7 +83,7 @@
public void generate(NodeLIRBuilderTool gen) {
assert constant != null : "Expected the value to fold: " + value;
Value result;
- if (constant instanceof HotSpotObjectConstant || constant instanceof HotSpotConstantPoolObject) {
+ if (constant instanceof HotSpotObjectConstant) {
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadObjectAddress(constant);
} else if (constant instanceof HotSpotMetaspaceConstant) {
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadMetaspaceAddress(constant, action);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java Fri Jun 28 14:36:42 2019 +0530
@@ -45,7 +45,6 @@
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.word.Word;
-import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
import jdk.vm.ci.meta.Constant;
@@ -101,7 +100,7 @@
Value result;
LIRFrameState fs = gen.state(this);
assert fs != null : "The stateAfter is null";
- if (constant instanceof HotSpotObjectConstant || constant instanceof HotSpotConstantPoolObject) {
+ if (constant instanceof HotSpotObjectConstant) {
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitObjectConstantRetrieval(constant, stringValue, fs);
} else if (constant instanceof HotSpotMetaspaceConstant) {
if (action == HotSpotConstantLoadAction.RESOLVE) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/AheadOfTimeVerificationPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,9 +28,9 @@
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.phases.VerifyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
import jdk.vm.ci.meta.JavaKind;
@@ -41,10 +41,10 @@
*
* @see LoadJavaMirrorWithKlassPhase
*/
-public class AheadOfTimeVerificationPhase extends VerifyPhase<PhaseContext> {
+public class AheadOfTimeVerificationPhase extends VerifyPhase<CoreProviders> {
@Override
- protected void verify(StructuredGraph graph, PhaseContext context) {
+ protected void verify(StructuredGraph graph, CoreProviders context) {
for (ConstantNode node : getConstantNodes(graph)) {
if (isIllegalObjectConstant(node)) {
throw new VerificationError("illegal object constant: " + node);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -44,9 +44,9 @@
import org.graalvm.compiler.nodes.memory.FloatingReadNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
@@ -68,7 +68,7 @@
*
* @see AheadOfTimeVerificationPhase
*/
-public class LoadJavaMirrorWithKlassPhase extends BasePhase<PhaseContext> {
+public class LoadJavaMirrorWithKlassPhase extends BasePhase<CoreProviders> {
private final CompressEncoding oopEncoding;
@@ -76,7 +76,7 @@
this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null;
}
- private ValueNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, JavaConstant constant) {
+ private ValueNode getClassConstantReplacement(StructuredGraph graph, CoreProviders context, JavaConstant constant) {
if (constant instanceof HotSpotObjectConstant) {
ConstantReflectionProvider constantReflection = context.getConstantReflection();
ResolvedJavaType type = constantReflection.asJavaType(constant);
@@ -131,7 +131,7 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
for (ConstantNode node : getConstantNodes(graph)) {
JavaConstant constant = node.asJavaConstant();
ValueNode freadNode = getClassConstantReplacement(graph, context, constant);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -282,7 +282,7 @@
NodeIterable<EntryMarkerNode> osrNodes = graph.getNodes(EntryMarkerNode.TYPE);
EntryMarkerNode osr = osrNodes.first();
if (osr == null) {
- throw new PermanentBailoutException("No OnStackReplacementNode generated");
+ throw new GraalError("No OnStackReplacementNode generated");
}
if (osrNodes.count() > 1) {
throw new GraalError("Multiple OnStackReplacementNodes generated");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.phases;
-
-import org.graalvm.compiler.debug.DebugCloseable;
-import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.gc.g1.G1BarrierSet;
-import org.graalvm.compiler.hotspot.gc.shared.BarrierSet;
-import org.graalvm.compiler.hotspot.gc.shared.CardTableBarrierSet;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
-import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
-import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.nodes.memory.WriteNode;
-import org.graalvm.compiler.phases.Phase;
-
-public class WriteBarrierAdditionPhase extends Phase {
-
- private BarrierSet barrierSet;
-
- public WriteBarrierAdditionPhase(GraalHotSpotVMConfig config) {
- this.barrierSet = createBarrierSet(config);
- }
-
- @SuppressWarnings("try")
- @Override
- protected void run(StructuredGraph graph) {
- for (Node n : graph.getNodes()) {
- try (DebugCloseable scope = n.graph().withNodeSourcePosition(n)) {
- if (n instanceof ReadNode) {
- barrierSet.addReadNodeBarriers((ReadNode) n, graph);
- } else if (n instanceof WriteNode) {
- barrierSet.addWriteNodeBarriers((WriteNode) n, graph);
- } else if (n instanceof LoweredAtomicReadAndWriteNode) {
- LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n;
- barrierSet.addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph);
- } else if (n instanceof AbstractCompareAndSwapNode) {
- barrierSet.addCASBarriers((AbstractCompareAndSwapNode) n, graph);
- } else if (n instanceof ArrayRangeWrite) {
- ArrayRangeWrite node = (ArrayRangeWrite) n;
- if (node.writesObjectArray()) {
- barrierSet.addArrayRangeBarriers(node, graph);
- }
- }
- }
- }
- }
-
- @Override
- public boolean checkContract() {
- return false;
- }
-
- private BarrierSet createBarrierSet(GraalHotSpotVMConfig config) {
- if (config.useG1GC) {
- return createG1BarrierSet(config);
- } else {
- return createCardTableBarrierSet(config);
- }
- }
-
- protected BarrierSet createCardTableBarrierSet(GraalHotSpotVMConfig config) {
- return new CardTableBarrierSet(config);
- }
-
- protected BarrierSet createG1BarrierSet(GraalHotSpotVMConfig config) {
- return new G1BarrierSet(config);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-
-package org.graalvm.compiler.hotspot.phases;
-
-import java.util.Iterator;
-
-import org.graalvm.compiler.debug.GraalError;
-import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.graph.NodeFlood;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.ArrayRangeWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.ObjectWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
-import org.graalvm.compiler.nodeinfo.Verbosity;
-import org.graalvm.compiler.nodes.DeoptimizingNode;
-import org.graalvm.compiler.nodes.FixedWithNextNode;
-import org.graalvm.compiler.nodes.LoopBeginNode;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
-import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
-import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;
-import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode;
-import org.graalvm.compiler.nodes.memory.FixedAccessNode;
-import org.graalvm.compiler.nodes.memory.HeapAccess;
-import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.nodes.memory.WriteNode;
-import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
-import org.graalvm.compiler.nodes.type.StampTool;
-import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.compiler.phases.Phase;
-
-/**
- * Verification phase that checks if, for every write, at least one write barrier is present at all
- * paths leading to the previous safepoint. For every write, necessitating a write barrier, a
- * bottom-up traversal of the graph is performed up to the previous safepoints via all possible
- * paths. If, for a certain path, no write barrier satisfying the processed write is found, an
- * assertion is generated.
- */
-public class WriteBarrierVerificationPhase extends Phase {
-
- private final GraalHotSpotVMConfig config;
-
- public WriteBarrierVerificationPhase(GraalHotSpotVMConfig config) {
- this.config = config;
- }
-
- @Override
- protected void run(StructuredGraph graph) {
- processWrites(graph);
- }
-
- private void processWrites(StructuredGraph graph) {
- for (Node node : graph.getNodes()) {
- if (isObjectWrite(node) || isObjectArrayRangeWrite(node)) {
- if (node instanceof WriteNode) {
- WriteNode writeNode = (WriteNode) node;
- if (StampTool.isPointerAlwaysNull(writeNode.value())) {
- continue;
- }
- }
- validateWrite(node);
- }
- }
- }
-
- private void validateWrite(Node write) {
- /*
- * The currently validated write is checked in order to discover if it has an appropriate
- * attached write barrier.
- */
- if (hasAttachedBarrier((FixedWithNextNode) write)) {
- return;
- }
- NodeFlood frontier = write.graph().createNodeFlood();
- expandFrontier(frontier, write);
- Iterator<Node> iterator = frontier.iterator();
- while (iterator.hasNext()) {
- Node currentNode = iterator.next();
- if (isSafepoint(currentNode)) {
- throw new AssertionError("Write barrier must be present " + write.toString(Verbosity.All) + " / " + write.inputs());
- }
- if (useG1GC()) {
- if (!(currentNode instanceof G1PostWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode))) {
- expandFrontier(frontier, currentNode);
- }
- } else {
- if (!(currentNode instanceof SerialWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode)) ||
- ((currentNode instanceof SerialWriteBarrier) && !validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode))) {
- expandFrontier(frontier, currentNode);
- }
- }
- }
- }
-
- private boolean useG1GC() {
- return config.useG1GC;
- }
-
- private boolean hasAttachedBarrier(FixedWithNextNode node) {
- final Node next = node.next();
- final Node previous = node.predecessor();
- boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWrite) node).isInitialization());
- if (node instanceof WriteNode) {
- WriteNode writeNode = (WriteNode) node;
- if (config.useDeferredInitBarriers && writeNode.getLocationIdentity().isInit()) {
- return true;
- }
- if (writeNode.getLocationIdentity().isInit()) {
- validatePreBarrier = false;
- }
- }
- if (isObjectWrite(node)) {
- return (isObjectBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isObjectBarrier(node, previous));
- } else if (isObjectArrayRangeWrite(node)) {
- return (isArrayBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isArrayBarrier(node, previous));
- } else {
- return true;
- }
- }
-
- private static boolean isObjectBarrier(FixedWithNextNode node, final Node next) {
- return next instanceof ObjectWriteBarrier && validateBarrier((FixedAccessNode) node, (ObjectWriteBarrier) next);
- }
-
- private static boolean isArrayBarrier(FixedWithNextNode node, final Node next) {
- return (next instanceof ArrayRangeWriteBarrier) && ((ArrayRangeWrite) node).getAddress() == ((ArrayRangeWriteBarrier) next).getAddress();
- }
-
- private static boolean isObjectWrite(Node node) {
- // Read nodes with barrier attached (G1 Ref field) are not validated yet.
- return node instanceof FixedAccessNode && ((HeapAccess) node).getBarrierType() != BarrierType.NONE && !(node instanceof ReadNode);
- }
-
- private static boolean isObjectArrayRangeWrite(Node node) {
- return node instanceof ArrayRangeWrite && ((ArrayRangeWrite) node).writesObjectArray();
- }
-
- private static void expandFrontier(NodeFlood frontier, Node node) {
- for (Node previousNode : node.cfgPredecessors()) {
- if (previousNode != null) {
- frontier.add(previousNode);
- }
- }
- }
-
- private static boolean isSafepoint(Node node) {
- if (node instanceof FixedAccessNode) {
- // Implicit null checks on reads or writes do not count.
- return false;
- }
- /*
- * LoopBegin nodes are also treated as safepoints since a bottom-up analysis is performed
- * and loop safepoints are placed before LoopEnd nodes. Possible elimination of write
- * barriers inside loops, derived from writes outside loops, can not be permitted.
- */
- return ((node instanceof DeoptimizingNode) && ((DeoptimizingNode) node).canDeoptimize()) || (node instanceof LoopBeginNode);
- }
-
- private static ValueNode getValueWritten(FixedWithNextNode write) {
- if (write instanceof WriteNode) {
- return ((WriteNode) write).value();
- } else if (write instanceof LogicCompareAndSwapNode) {
- return ((LogicCompareAndSwapNode) write).getNewValue();
- } else if (write instanceof LoweredAtomicReadAndWriteNode) {
- return ((LoweredAtomicReadAndWriteNode) write).getNewValue();
- } else {
- throw GraalError.shouldNotReachHere(String.format("unexpected write node %s", write));
- }
- }
-
- private static boolean validateBarrier(FixedAccessNode write, ObjectWriteBarrier barrier) {
- assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof ValueCompareAndSwapNode ||
- write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write;
- if (!barrier.usePrecise()) {
- if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) {
- return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) write.getAddress()).getBase());
- }
- }
- return barrier.getAddress() == write.getAddress();
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,10 +30,6 @@
import java.util.Iterator;
import java.util.List;
-import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
-import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.ResolvedJavaType;
-
import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
@@ -43,12 +39,16 @@
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.graph.MergeableState;
import org.graalvm.compiler.phases.graph.PostOrderNodeIterator;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
-public class EliminateRedundantInitializationPhase extends BasePhase<PhaseContext> {
+import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+public class EliminateRedundantInitializationPhase extends BasePhase<CoreProviders> {
/**
* Find each {@link Invoke} that has a corresponding {@link InitializeKlassNode}. These
* {@link InitializeKlassNode} are redundant and are removed.
@@ -252,7 +252,7 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
removeInitsAtStaticCalls(graph);
removeRedundantInits(graph);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -61,12 +61,12 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.cfg.Block;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
@@ -78,7 +78,7 @@
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaType;
-public class ReplaceConstantNodesPhase extends BasePhase<PhaseContext> {
+public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
private final boolean verifyFingerprints;
@@ -448,7 +448,7 @@
* @param node
* @param context
*/
- private static void handleLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, LoadMethodCountersNode node, PhaseContext context) {
+ private static void handleLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, LoadMethodCountersNode node, CoreProviders context) {
ResolvedJavaType type = node.getMethod().getDeclaringClass();
Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull());
ConstantReflectionProvider constantReflection = context.getConstantReflection();
@@ -466,7 +466,7 @@
* @param stateMapper
* @param context
*/
- private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, PhaseContext context) {
+ private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, CoreProviders context) {
new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);
for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) {
@@ -496,7 +496,7 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
FrameStateMapperClosure stateMapper = new FrameStateMapperClosure(graph);
ReentrantNodeIterator.apply(stateMapper, graph.start(), null);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -46,16 +46,16 @@
import org.graalvm.compiler.nodes.calc.MulNode;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.ResolvedJavaMethod;
-public class FinalizeProfileNodesPhase extends BasePhase<PhaseContext> {
+public class FinalizeProfileNodesPhase extends BasePhase<CoreProviders> {
private int inlineeInvokeNotificationFreqLog;
public static class Options {
@@ -156,7 +156,7 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
if (simpleMethodHeuristic(graph)) {
removeAllProfilingNodes(graph);
return;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.replacements;
+
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
+
+import org.graalvm.compiler.core.common.CompressEncoding;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
+import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
+import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.gc.G1ArrayRangePostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ArrayRangePreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ReferentFieldReadBarrier;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.ReplacementsUtil;
+import org.graalvm.compiler.replacements.SnippetCounter.Group;
+import org.graalvm.compiler.replacements.SnippetCounter.Group.Factory;
+import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
+import org.graalvm.compiler.replacements.gc.G1WriteBarrierSnippets;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.WordFactory;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.JavaKind;
+
+public final class HotSpotG1WriteBarrierSnippets extends G1WriteBarrierSnippets {
+ public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class);
+ public static final ForeignCallDescriptor G1WBPOSTCALL = new ForeignCallDescriptor("write_barrier_post", void.class, Word.class);
+ public static final ForeignCallDescriptor VALIDATE_OBJECT = new ForeignCallDescriptor("validate_object", boolean.class, Word.class, Word.class);
+
+ private final GraalHotSpotVMConfig config;
+ private final Register threadRegister;
+
+ public HotSpotG1WriteBarrierSnippets(GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) {
+ this.config = config;
+ this.threadRegister = registers.getThreadRegister();
+ }
+
+ @Override
+ protected Word getThread() {
+ return HotSpotReplacementsUtil.registerAsWord(threadRegister);
+ }
+
+ @Override
+ protected int wordSize() {
+ return HotSpotReplacementsUtil.wordSize();
+ }
+
+ @Override
+ protected int objectArrayIndexScale() {
+ return ReplacementsUtil.arrayIndexScale(INJECTED_METAACCESS, JavaKind.Object);
+ }
+
+ @Override
+ protected int satbQueueMarkingOffset() {
+ return HotSpotReplacementsUtil.g1SATBQueueMarkingOffset(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected int satbQueueBufferOffset() {
+ return HotSpotReplacementsUtil.g1SATBQueueBufferOffset(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected int satbQueueIndexOffset() {
+ return HotSpotReplacementsUtil.g1SATBQueueIndexOffset(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected int cardQueueBufferOffset() {
+ return HotSpotReplacementsUtil.g1CardQueueBufferOffset(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected int cardQueueIndexOffset() {
+ return HotSpotReplacementsUtil.g1CardQueueIndexOffset(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected byte dirtyCardValue() {
+ return HotSpotReplacementsUtil.dirtyCardValue(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected byte youngCardValue() {
+ return HotSpotReplacementsUtil.g1YoungCardValue(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected Word cardTableAddress() {
+ return WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress());
+ }
+
+ @Override
+ protected int cardTableShift() {
+ return HotSpotReplacementsUtil.cardTableShift(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected int logOfHeapRegionGrainBytes() {
+ return GraalHotSpotVMConfigNode.logOfHeapRegionGrainBytes();
+ }
+
+ @Override
+ protected ForeignCallDescriptor preWriteBarrierCallDescriptor() {
+ return G1WBPRECALL;
+ }
+
+ @Override
+ protected ForeignCallDescriptor postWriteBarrierCallDescriptor() {
+ return G1WBPOSTCALL;
+ }
+
+ @Override
+ protected boolean verifyOops() {
+ return HotSpotReplacementsUtil.verifyOops(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected boolean verifyBarrier() {
+ return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC;
+ }
+
+ @Override
+ protected long gcTotalCollectionsAddress() {
+ return HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ protected ForeignCallDescriptor verifyOopCallDescriptor() {
+ return HotSpotForeignCallsProviderImpl.VERIFY_OOP;
+ }
+
+ @Override
+ protected ForeignCallDescriptor validateObjectCallDescriptor() {
+ return VALIDATE_OBJECT;
+ }
+
+ @Override
+ protected ForeignCallDescriptor printfCallDescriptor() {
+ return Log.LOG_PRINTF;
+ }
+
+ public static class Templates extends AbstractTemplates {
+ private final SnippetInfo g1PreWriteBarrier;
+ private final SnippetInfo g1ReferentReadBarrier;
+ private final SnippetInfo g1PostWriteBarrier;
+ private final SnippetInfo g1ArrayRangePreWriteBarrier;
+ private final SnippetInfo g1ArrayRangePostWriteBarrier;
+
+ private final G1WriteBarrierLowerer lowerer;
+
+ public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) {
+ super(options, factories, providers, providers.getSnippetReflection(), target);
+ this.lowerer = new HotspotG1WriteBarrierLowerer(config, factory);
+
+ HotSpotG1WriteBarrierSnippets receiver = new HotSpotG1WriteBarrierSnippets(config, providers.getRegisters());
+ g1PreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PreWriteBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION,
+ SATB_QUEUE_BUFFER_LOCATION);
+ g1ReferentReadBarrier = g1PreWriteBarrier;
+ g1PostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION, CARD_QUEUE_INDEX_LOCATION,
+ CARD_QUEUE_BUFFER_LOCATION);
+ g1ArrayRangePreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION,
+ SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION);
+ g1ArrayRangePostWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", null, receiver, GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION,
+ CARD_QUEUE_INDEX_LOCATION, CARD_QUEUE_BUFFER_LOCATION);
+ }
+
+ public void lower(G1PreWriteBarrier barrier, LoweringTool tool) {
+ lowerer.lower(this, g1PreWriteBarrier, barrier, tool);
+ }
+
+ public void lower(G1ReferentFieldReadBarrier barrier, LoweringTool tool) {
+ lowerer.lower(this, g1ReferentReadBarrier, barrier, tool);
+ }
+
+ public void lower(G1PostWriteBarrier barrier, LoweringTool tool) {
+ lowerer.lower(this, g1PostWriteBarrier, barrier, tool);
+ }
+
+ public void lower(G1ArrayRangePreWriteBarrier barrier, LoweringTool tool) {
+ lowerer.lower(this, g1ArrayRangePreWriteBarrier, barrier, tool);
+ }
+
+ public void lower(G1ArrayRangePostWriteBarrier barrier, LoweringTool tool) {
+ lowerer.lower(this, g1ArrayRangePostWriteBarrier, barrier, tool);
+ }
+ }
+
+ static final class HotspotG1WriteBarrierLowerer extends G1WriteBarrierLowerer {
+ private final CompressEncoding oopEncoding;
+
+ HotspotG1WriteBarrierLowerer(GraalHotSpotVMConfig config, Factory factory) {
+ super(factory);
+ oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null;
+ }
+
+ @Override
+ public ValueNode uncompress(ValueNode expected) {
+ assert oopEncoding != null;
+ return HotSpotCompressionNode.uncompress(expected, oopEncoding);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.replacements;
+
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG;
+
+import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
+import org.graalvm.compiler.nodes.gc.SerialArrayRangeWriteBarrier;
+import org.graalvm.compiler.nodes.gc.SerialWriteBarrier;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.ReplacementsUtil;
+import org.graalvm.compiler.replacements.SnippetCounter.Group;
+import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
+import org.graalvm.compiler.replacements.gc.SerialWriteBarrierSnippets;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.WordFactory;
+
+import jdk.vm.ci.code.TargetDescription;
+
+public class HotSpotSerialWriteBarrierSnippets extends SerialWriteBarrierSnippets {
+ private final GraalHotSpotVMConfig config;
+
+ public HotSpotSerialWriteBarrierSnippets(GraalHotSpotVMConfig config) {
+ this.config = config;
+ }
+
+ @Override
+ public Word cardTableAddress() {
+ return WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress());
+ }
+
+ @Override
+ public int cardTableShift() {
+ return HotSpotReplacementsUtil.cardTableShift(INJECTED_VMCONFIG);
+ }
+
+ @Override
+ public boolean verifyBarrier() {
+ return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC;
+ }
+
+ @Override
+ protected byte dirtyCardValue() {
+ return config.dirtyCardValue;
+ }
+
+ public static class Templates extends AbstractTemplates {
+ private final SnippetInfo serialImpreciseWriteBarrier;
+ private final SnippetInfo serialPreciseWriteBarrier;
+ private final SnippetInfo serialArrayRangeWriteBarrier;
+
+ private final SerialWriteBarrierLowerer lowerer;
+
+ public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) {
+ super(options, factories, providers, providers.getSnippetReflection(), target);
+ this.lowerer = new SerialWriteBarrierLowerer(factory);
+
+ HotSpotSerialWriteBarrierSnippets receiver = new HotSpotSerialWriteBarrierSnippets(config);
+ serialImpreciseWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialImpreciseWriteBarrier", null, receiver, GC_CARD_LOCATION);
+ serialPreciseWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialPreciseWriteBarrier", null, receiver, GC_CARD_LOCATION);
+ serialArrayRangeWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialArrayRangeWriteBarrier", null, receiver, GC_CARD_LOCATION);
+ }
+
+ public void lower(SerialWriteBarrier barrier, LoweringTool tool) {
+ lowerer.lower(this, serialPreciseWriteBarrier, serialImpreciseWriteBarrier, barrier, tool);
+ }
+
+ public void lower(SerialArrayRangeWriteBarrier barrier, LoweringTool tool) {
+ lowerer.lower(this, serialArrayRangeWriteBarrier, barrier, tool);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/Log.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.replacements;
+
+import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
+
+import java.io.PrintStream;
+
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
+import org.graalvm.compiler.graph.Node.NodeIntrinsic;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
+import org.graalvm.compiler.word.Word;
+
+import jdk.vm.ci.meta.JavaKind;
+
+//JaCoCo Exclude
+
+/**
+ * Provides {@link PrintStream}-like logging facility.
+ */
+public final class Log {
+
+ public static final ForeignCallDescriptor LOG_PRIMITIVE = new ForeignCallDescriptor("logPrimitive", void.class, int.class, long.class, boolean.class);
+ public static final ForeignCallDescriptor LOG_OBJECT = new ForeignCallDescriptor("logObject", void.class, Object.class, boolean.class, boolean.class);
+ public static final ForeignCallDescriptor LOG_PRINTF = new ForeignCallDescriptor("logPrintf", void.class, Word.class, long.class, long.class, long.class);
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native void log(@ConstantNodeParameter ForeignCallDescriptor logObject, Object object, boolean asString, boolean newline);
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native void log(@ConstantNodeParameter ForeignCallDescriptor logPrimitive, int typeChar, long value, boolean newline);
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native void printf(@ConstantNodeParameter ForeignCallDescriptor logPrintf, Word format, long v1, long v2, long v3);
+
+ public static void print(boolean value) {
+ log(LOG_PRIMITIVE, JavaKind.Boolean.getTypeChar(), value ? 1L : 0L, false);
+ }
+
+ public static void print(byte value) {
+ log(LOG_PRIMITIVE, JavaKind.Byte.getTypeChar(), value, false);
+ }
+
+ public static void print(char value) {
+ log(LOG_PRIMITIVE, JavaKind.Char.getTypeChar(), value, false);
+ }
+
+ public static void print(short value) {
+ log(LOG_PRIMITIVE, JavaKind.Short.getTypeChar(), value, false);
+ }
+
+ public static void print(int value) {
+ log(LOG_PRIMITIVE, JavaKind.Int.getTypeChar(), value, false);
+ }
+
+ public static void print(long value) {
+ log(LOG_PRIMITIVE, JavaKind.Long.getTypeChar(), value, false);
+ }
+
+ /**
+ * Prints a formatted string to the log stream.
+ *
+ * @param format a C style printf format value that can contain at most one conversion specifier
+ * (i.e., a sequence of characters starting with '%').
+ * @param value the value associated with the conversion specifier
+ */
+ public static void printf(String format, long value) {
+ printf(LOG_PRINTF, cstring(format), value, 0L, 0L);
+ }
+
+ public static void printf(String format, long v1, long v2) {
+ printf(LOG_PRINTF, cstring(format), v1, v2, 0L);
+ }
+
+ public static void printf(String format, long v1, long v2, long v3) {
+ printf(LOG_PRINTF, cstring(format), v1, v2, v3);
+ }
+
+ public static void print(float value) {
+ if (Float.isNaN(value)) {
+ print("NaN");
+ } else if (value == Float.POSITIVE_INFINITY) {
+ print("Infinity");
+ } else if (value == Float.NEGATIVE_INFINITY) {
+ print("-Infinity");
+ } else {
+ log(LOG_PRIMITIVE, JavaKind.Float.getTypeChar(), Float.floatToRawIntBits(value), false);
+ }
+ }
+
+ public static void print(double value) {
+ if (Double.isNaN(value)) {
+ print("NaN");
+ } else if (value == Double.POSITIVE_INFINITY) {
+ print("Infinity");
+ } else if (value == Double.NEGATIVE_INFINITY) {
+ print("-Infinity");
+ } else {
+ log(LOG_PRIMITIVE, JavaKind.Double.getTypeChar(), Double.doubleToRawLongBits(value), false);
+ }
+ }
+
+ public static void print(String value) {
+ log(LOG_OBJECT, value, true, false);
+ }
+
+ public static void printObject(Object o) {
+ log(LOG_OBJECT, o, false, false);
+ }
+
+ public static void println(boolean value) {
+ log(LOG_PRIMITIVE, JavaKind.Boolean.getTypeChar(), value ? 1L : 0L, true);
+ }
+
+ public static void println(byte value) {
+ log(LOG_PRIMITIVE, JavaKind.Byte.getTypeChar(), value, true);
+ }
+
+ public static void println(char value) {
+ log(LOG_PRIMITIVE, JavaKind.Char.getTypeChar(), value, true);
+ }
+
+ public static void println(short value) {
+ log(LOG_PRIMITIVE, JavaKind.Short.getTypeChar(), value, true);
+ }
+
+ public static void println(int value) {
+ log(LOG_PRIMITIVE, JavaKind.Int.getTypeChar(), value, true);
+ }
+
+ public static void println(long value) {
+ log(LOG_PRIMITIVE, JavaKind.Long.getTypeChar(), value, true);
+ }
+
+ public static void println(float value) {
+ if (Float.isNaN(value)) {
+ println("NaN");
+ } else if (value == Float.POSITIVE_INFINITY) {
+ println("Infinity");
+ } else if (value == Float.NEGATIVE_INFINITY) {
+ println("-Infinity");
+ } else {
+ log(LOG_PRIMITIVE, JavaKind.Float.getTypeChar(), Float.floatToRawIntBits(value), true);
+ }
+ }
+
+ public static void println(double value) {
+ if (Double.isNaN(value)) {
+ println("NaN");
+ } else if (value == Double.POSITIVE_INFINITY) {
+ println("Infinity");
+ } else if (value == Double.NEGATIVE_INFINITY) {
+ println("-Infinity");
+ } else {
+ log(LOG_PRIMITIVE, JavaKind.Double.getTypeChar(), Double.doubleToRawLongBits(value), true);
+ }
+ }
+
+ public static void println(String value) {
+ log(LOG_OBJECT, value, true, true);
+ }
+
+ public static void printlnObject(Object o) {
+ log(LOG_OBJECT, o, false, true);
+ }
+
+ public static void println() {
+ println("");
+ }
+}
+
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,7 +122,6 @@
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
-import org.graalvm.compiler.replacements.Log;
import org.graalvm.compiler.replacements.SnippetCounter;
import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
@@ -753,7 +752,8 @@
public static class Templates extends AbstractTemplates {
private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter");
- private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit");
+ private final SnippetInfo monitorexit = snippet(MonitorSnippets.class, "monitorexit", DISPLACED_MARK_WORD_LOCATION, OBJECT_MONITOR_OWNER_LOCATION, OBJECT_MONITOR_CXQ_LOCATION,
+ OBJECT_MONITOR_ENTRY_LIST_LOCATION, OBJECT_MONITOR_RECURSION_LOCATION, OBJECT_MONITOR_SUCC_LOCATION);
private final SnippetInfo monitorenterStub = snippet(MonitorSnippets.class, "monitorenterStub");
private final SnippetInfo monitorexitStub = snippet(MonitorSnippets.class, "monitorexitStub");
private final SnippetInfo initCounter = snippet(MonitorSnippets.class, "initCounter");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Fri Jun 28 14:36:42 2019 +0530
@@ -38,6 +38,7 @@
import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY;
import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY_OR_NULL;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_STATE_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION;
@@ -604,7 +605,7 @@
} else {
// Use Word instead of int to avoid extension to long in generated code
Word off = WordFactory.signed(offset);
- if (useBulkZeroing && probability(SLOW_PATH_PROBABILITY, size >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) {
+ if (useBulkZeroing && value == 0 && probability(SLOW_PATH_PROBABILITY, (size - offset) >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) {
if (theCounters != null && theCounters.instanceBulkInit != null) {
theCounters.instanceBulkInit.inc();
}
@@ -623,7 +624,6 @@
for (; off.rawValue() < size; off = off.add(8)) {
memory.initializeLong(off, value, LocationIdentity.init());
}
-
}
}
}
@@ -714,9 +714,10 @@
public static class Templates extends AbstractTemplates {
- private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
+ private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION,
+ PROTOTYPE_MARK_WORD_LOCATION);
private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
- TLAB_END_LOCATION);
+ TLAB_END_LOCATION, PROTOTYPE_MARK_WORD_LOCATION);
private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
@@ -724,7 +725,7 @@
private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
TLAB_END_LOCATION);
private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION,
- TLAB_END_LOCATION);
+ TLAB_END_LOCATION, PROTOTYPE_MARK_WORD_LOCATION, CLASS_STATE_LOCATION);
private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", TLAB_TOP_LOCATION, TLAB_END_LOCATION);
private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", TLAB_TOP_LOCATION, TLAB_END_LOCATION);
private final SnippetInfo verifyHeap = snippet(NewObjectSnippets.class, "verifyHeap");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,9 +24,8 @@
package org.graalvm.compiler.hotspot.replacements;
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_METAACCESS;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.Fold;
@@ -37,6 +36,7 @@
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
import org.graalvm.compiler.replacements.ReplacementsUtil;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.internal.vm.compiler.word.WordFactory;
@@ -46,7 +46,7 @@
@ClassSubstitution(className = "sun.security.provider.SHA2", optional = true)
public class SHA2Substitutions {
- public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
+ public static final String implCompressName = JavaVersionUtil.JAVA_SPEC <= 8 ? "implCompress" : "implCompress0";
@MethodSubstitution(isStatic = false)
static void implCompress0(Object receiver, byte[] buf, int ofs) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,7 +26,6 @@
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.Fold;
@@ -38,6 +37,7 @@
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
import org.graalvm.compiler.replacements.ReplacementsUtil;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.internal.vm.compiler.word.WordFactory;
@@ -47,7 +47,7 @@
@ClassSubstitution(className = "sun.security.provider.SHA5", optional = true)
public class SHA5Substitutions {
- public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
+ public static final String implCompressName = JavaVersionUtil.JAVA_SPEC <= 8 ? "implCompress" : "implCompress0";
@MethodSubstitution(isStatic = false)
static void implCompress0(Object receiver, byte[] buf, int ofs) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,7 +26,6 @@
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_INTRINSIC_CONTEXT;
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.Fold;
@@ -38,6 +37,7 @@
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
import org.graalvm.compiler.replacements.ReplacementsUtil;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.internal.vm.compiler.word.WordFactory;
@@ -47,7 +47,7 @@
@ClassSubstitution(className = "sun.security.provider.SHA", optional = true)
public class SHASubstitutions {
- public static final String implCompressName = Java8OrEarlier ? "implCompress" : "implCompress0";
+ public static final String implCompressName = JavaVersionUtil.JAVA_SPEC <= 8 ? "implCompress" : "implCompress0";
@MethodSubstitution(isStatic = false)
static void implCompress0(Object receiver, byte[] buf, int ofs) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,621 +0,0 @@
-/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.hotspot.replacements;
-
-import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_METAACCESS;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.cardTableShift;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.dirtyCardValue;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.g1CardQueueBufferOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.g1CardQueueIndexOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.g1SATBQueueBufferOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.g1SATBQueueIndexOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.g1SATBQueueMarkingOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.g1YoungCardValue;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
-import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
-
-import org.graalvm.compiler.api.replacements.Snippet;
-import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
-import org.graalvm.compiler.core.common.CompressEncoding;
-import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
-import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
-import org.graalvm.compiler.graph.Node.NodeIntrinsic;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePreWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.g1.G1ReferentFieldReadBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialArrayRangeWriteBarrier;
-import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
-import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
-import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
-import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
-import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode;
-import org.graalvm.compiler.hotspot.nodes.VMErrorNode;
-import org.graalvm.compiler.nodes.NamedLocationIdentity;
-import org.graalvm.compiler.nodes.NodeView;
-import org.graalvm.compiler.nodes.PiNode;
-import org.graalvm.compiler.nodes.SnippetAnchorNode;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode;
-import org.graalvm.compiler.nodes.extended.ForeignCallNode;
-import org.graalvm.compiler.nodes.extended.MembarNode;
-import org.graalvm.compiler.nodes.extended.NullCheckNode;
-import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode.Address;
-import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
-import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.compiler.nodes.type.NarrowOopStamp;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.replacements.Log;
-import org.graalvm.compiler.replacements.ReplacementsUtil;
-import org.graalvm.compiler.replacements.SnippetCounter;
-import org.graalvm.compiler.replacements.SnippetCounter.Group;
-import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
-import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
-import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
-import org.graalvm.compiler.replacements.Snippets;
-import org.graalvm.compiler.replacements.nodes.AssertionNode;
-import org.graalvm.compiler.replacements.nodes.DirectStoreNode;
-import org.graalvm.compiler.word.Word;
-import jdk.internal.vm.compiler.word.LocationIdentity;
-import jdk.internal.vm.compiler.word.Pointer;
-import jdk.internal.vm.compiler.word.UnsignedWord;
-import jdk.internal.vm.compiler.word.WordFactory;
-
-import jdk.vm.ci.code.Register;
-import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.JavaKind;
-
-public class WriteBarrierSnippets implements Snippets {
-
- static class Counters {
- Counters(SnippetCounter.Group.Factory factory) {
- Group countersWriteBarriers = factory.createSnippetCounterGroup("WriteBarriers");
- serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers");
- g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers");
- g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers");
- g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers");
- g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers");
- g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier",
- "Number of effective G1 Post Write Barriers (after passing the XOR test)");
- g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier",
- "Number of effective G1 Post Write Barriers (after passing the NULL test)");
- g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers");
-
- }
-
- final SnippetCounter serialWriteBarrierCounter;
- final SnippetCounter g1AttemptedPreWriteBarrierCounter;
- final SnippetCounter g1EffectivePreWriteBarrierCounter;
- final SnippetCounter g1ExecutedPreWriteBarrierCounter;
- final SnippetCounter g1AttemptedPostWriteBarrierCounter;
- final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter;
- final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter;
- final SnippetCounter g1ExecutedPostWriteBarrierCounter;
- }
-
- public static final LocationIdentity GC_CARD_LOCATION = NamedLocationIdentity.mutable("GC-Card");
- public static final LocationIdentity GC_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Log");
- public static final LocationIdentity GC_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Index");
-
- private static void serialWriteBarrier(Pointer ptr, Counters counters) {
- counters.serialWriteBarrierCounter.inc();
- final long startAddress = GraalHotSpotVMConfigNode.cardTableAddress();
- Word base = (Word) ptr.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG));
- if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) {
- base.writeByte((int) startAddress, (byte) 0, GC_CARD_LOCATION);
- } else {
- base.writeByte(WordFactory.unsigned(startAddress), (byte) 0, GC_CARD_LOCATION);
- }
- }
-
- @Snippet
- public static void serialImpreciseWriteBarrier(Object object, @ConstantParameter boolean verifyBarrier, @ConstantParameter Counters counters) {
- if (verifyBarrier) {
- verifyNotArray(object);
- }
- serialWriteBarrier(Word.objectToTrackedPointer(object), counters);
- }
-
- @Snippet
- public static void serialPreciseWriteBarrier(Address address, @ConstantParameter Counters counters) {
- serialWriteBarrier(Word.fromAddress(address), counters);
- }
-
- @Snippet
- public static void serialArrayRangeWriteBarrier(Address address, int length, @ConstantParameter int elementStride) {
- if (length == 0) {
- return;
- }
- int cardShift = cardTableShift(INJECTED_VMCONFIG);
- final long cardStart = GraalHotSpotVMConfigNode.cardTableAddress();
- long start = getPointerToFirstArrayElement(address, length, elementStride) >>> cardShift;
- long end = getPointerToLastArrayElement(address, length, elementStride) >>> cardShift;
- long count = end - start + 1;
- while (count-- > 0) {
- DirectStoreNode.storeBoolean((start + cardStart) + count, false, JavaKind.Boolean);
- }
- }
-
- @Snippet
- public static void g1PreWriteBarrier(Address address, Object object, Object expectedObject, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck,
- @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, @ConstantParameter Counters counters) {
- if (nullCheck) {
- NullCheckNode.nullCheck(address);
- }
- Word thread = registerAsWord(threadRegister);
- verifyOop(object);
- Object fixedExpectedObject = FixedValueAnchorNode.getObject(expectedObject);
- Word field = Word.fromAddress(address);
- Pointer previousOop = Word.objectToTrackedPointer(fixedExpectedObject);
- byte markingValue = thread.readByte(g1SATBQueueMarkingOffset(INJECTED_VMCONFIG));
- int gcCycle = 0;
- if (trace) {
- Pointer gcTotalCollectionsAddress = WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG));
- gcCycle = (int) gcTotalCollectionsAddress.readLong(0);
- log(trace, "[%d] G1-Pre Thread %p Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue());
- log(trace, "[%d] G1-Pre Thread %p Expected Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(fixedExpectedObject).rawValue());
- log(trace, "[%d] G1-Pre Thread %p Field %p\n", gcCycle, thread.rawValue(), field.rawValue());
- log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue);
- log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L);
- }
- counters.g1AttemptedPreWriteBarrierCounter.inc();
- // If the concurrent marker is enabled, the barrier is issued.
- if (probability(NOT_FREQUENT_PROBABILITY, markingValue != (byte) 0)) {
- // If the previous value has to be loaded (before the write), the load is issued.
- // The load is always issued except the cases of CAS and referent field.
- if (probability(LIKELY_PROBABILITY, doLoad)) {
- previousOop = Word.objectToTrackedPointer(field.readObject(0, BarrierType.NONE));
- if (trace) {
- log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue());
- verifyOop(previousOop.toObject());
- }
- }
- counters.g1EffectivePreWriteBarrierCounter.inc();
- // If the previous value is null the barrier should not be issued.
- if (probability(FREQUENT_PROBABILITY, previousOop.notEqual(0))) {
- counters.g1ExecutedPreWriteBarrierCounter.inc();
- // If the thread-local SATB buffer is full issue a native call which will
- // initialize a new one and add the entry.
- Word indexAddress = thread.add(g1SATBQueueIndexOffset(INJECTED_VMCONFIG));
- Word indexValue = indexAddress.readWord(0);
- if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) {
- Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset(INJECTED_VMCONFIG));
- Word nextIndex = indexValue.subtract(wordSize());
- Word logAddress = bufferAddress.add(nextIndex);
- // Log the object to be marked as well as update the SATB's buffer next index.
- logAddress.writeWord(0, previousOop, GC_LOG_LOCATION);
- indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION);
- } else {
- g1PreBarrierStub(G1WBPRECALL, previousOop.toObject());
- }
- }
- }
- }
-
- @Snippet
- public static void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter boolean usePrecise, @ConstantParameter boolean verifyBarrier,
- @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, @ConstantParameter Counters counters) {
- Word thread = registerAsWord(threadRegister);
- Object fixedValue = FixedValueAnchorNode.getObject(value);
- verifyOop(object);
- verifyOop(fixedValue);
- validateObject(object, fixedValue);
- Pointer oop;
- if (usePrecise) {
- oop = Word.fromAddress(address);
- } else {
- if (verifyBarrier) {
- verifyNotArray(object);
- }
- oop = Word.objectToTrackedPointer(object);
- }
- int gcCycle = 0;
- if (trace) {
- Pointer gcTotalCollectionsAddress = WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG));
- gcCycle = (int) gcTotalCollectionsAddress.readLong(0);
- log(trace, "[%d] G1-Post Thread: %p Object: %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue());
- log(trace, "[%d] G1-Post Thread: %p Field: %p\n", gcCycle, thread.rawValue(), oop.rawValue());
- }
- Pointer writtenValue = Word.objectToTrackedPointer(fixedValue);
- // The result of the xor reveals whether the installed pointer crosses heap regions.
- // In case it does the write barrier has to be issued.
- final int logOfHeapRegionGrainBytes = GraalHotSpotVMConfigNode.logOfHeapRegionGrainBytes();
- UnsignedWord xorResult = (oop.xor(writtenValue)).unsignedShiftRight(logOfHeapRegionGrainBytes);
-
- // Calculate the address of the card to be enqueued to the
- // thread local card queue.
- UnsignedWord cardBase = oop.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG));
- final long startAddress = GraalHotSpotVMConfigNode.cardTableAddress();
- int displacement = 0;
- if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) {
- displacement = (int) startAddress;
- } else {
- cardBase = cardBase.add(WordFactory.unsigned(startAddress));
- }
- Word cardAddress = (Word) cardBase.add(displacement);
-
- counters.g1AttemptedPostWriteBarrierCounter.inc();
- if (probability(FREQUENT_PROBABILITY, xorResult.notEqual(0))) {
- counters.g1EffectiveAfterXORPostWriteBarrierCounter.inc();
-
- // If the written value is not null continue with the barrier addition.
- if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) {
- byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION);
- counters.g1EffectiveAfterNullPostWriteBarrierCounter.inc();
-
- // If the card is already dirty, (hence already enqueued) skip the insertion.
- if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue(INJECTED_VMCONFIG))) {
- MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION);
- byte cardByteReload = cardAddress.readByte(0, GC_CARD_LOCATION);
- if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue(INJECTED_VMCONFIG))) {
- log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), WordFactory.unsigned((int) cardByte).rawValue());
- cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION);
- counters.g1ExecutedPostWriteBarrierCounter.inc();
-
- // If the thread local card queue is full, issue a native call which will
- // initialize a new one and add the card entry.
- Word indexAddress = thread.add(g1CardQueueIndexOffset(INJECTED_VMCONFIG));
- Word indexValue = thread.readWord(g1CardQueueIndexOffset(INJECTED_VMCONFIG));
- if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) {
- Word bufferAddress = thread.readWord(g1CardQueueBufferOffset(INJECTED_VMCONFIG));
- Word nextIndex = indexValue.subtract(wordSize());
- Word logAddress = bufferAddress.add(nextIndex);
- // Log the object to be scanned as well as update
- // the card queue's next index.
- logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION);
- indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION);
- } else {
- g1PostBarrierStub(G1WBPOSTCALL, cardAddress);
- }
- }
- }
- }
- }
- }
-
- private static void verifyNotArray(Object object) {
- if (object != null) {
- // Manually build the null check and cast because we're in snippet that's lowered late.
- AssertionNode.assertion(false, !PiNode.piCastNonNull(object, SnippetAnchorNode.anchor()).getClass().isArray(), "imprecise card mark used with array");
- }
- }
-
- @Snippet
- public static void g1ArrayRangePreWriteBarrier(Address address, int length, @ConstantParameter int elementStride, @ConstantParameter Register threadRegister) {
- Word thread = registerAsWord(threadRegister);
- byte markingValue = thread.readByte(g1SATBQueueMarkingOffset(INJECTED_VMCONFIG));
- // If the concurrent marker is not enabled or the vector length is zero, return.
- if (markingValue == (byte) 0 || length == 0) {
- return;
- }
- Word bufferAddress = thread.readWord(g1SATBQueueBufferOffset(INJECTED_VMCONFIG));
- Word indexAddress = thread.add(g1SATBQueueIndexOffset(INJECTED_VMCONFIG));
- long indexValue = indexAddress.readWord(0).rawValue();
- final int scale = ReplacementsUtil.arrayIndexScale(INJECTED_METAACCESS, JavaKind.Object);
- long start = getPointerToFirstArrayElement(address, length, elementStride);
-
- for (int i = 0; i < length; i++) {
- Word arrElemPtr = WordFactory.pointer(start + i * scale);
- Pointer oop = Word.objectToTrackedPointer(arrElemPtr.readObject(0, BarrierType.NONE));
- verifyOop(oop.toObject());
- if (oop.notEqual(0)) {
- if (indexValue != 0) {
- indexValue = indexValue - wordSize();
- Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue));
- // Log the object to be marked as well as update the SATB's buffer next index.
- logAddress.writeWord(0, oop, GC_LOG_LOCATION);
- indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION);
- } else {
- g1PreBarrierStub(G1WBPRECALL, oop.toObject());
- }
- }
- }
- }
-
- @Snippet
- public static void g1ArrayRangePostWriteBarrier(Address address, int length, @ConstantParameter int elementStride, @ConstantParameter Register threadRegister) {
- if (length == 0) {
- return;
- }
- Word thread = registerAsWord(threadRegister);
- Word bufferAddress = thread.readWord(g1CardQueueBufferOffset(INJECTED_VMCONFIG));
- Word indexAddress = thread.add(g1CardQueueIndexOffset(INJECTED_VMCONFIG));
- long indexValue = thread.readWord(g1CardQueueIndexOffset(INJECTED_VMCONFIG)).rawValue();
-
- int cardShift = cardTableShift(INJECTED_VMCONFIG);
- final long cardStart = GraalHotSpotVMConfigNode.cardTableAddress();
- long start = getPointerToFirstArrayElement(address, length, elementStride) >>> cardShift;
- long end = getPointerToLastArrayElement(address, length, elementStride) >>> cardShift;
- long count = end - start + 1;
-
- while (count-- > 0) {
- Word cardAddress = WordFactory.unsigned((start + cardStart) + count);
- byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION);
- // If the card is already dirty, (hence already enqueued) skip the insertion.
- if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue(INJECTED_VMCONFIG))) {
- MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION);
- byte cardByteReload = cardAddress.readByte(0, GC_CARD_LOCATION);
- if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue(INJECTED_VMCONFIG))) {
- cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION);
- // If the thread local card queue is full, issue a native call which will
- // initialize a new one and add the card entry.
- if (indexValue != 0) {
- indexValue = indexValue - wordSize();
- Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue));
- // Log the object to be scanned as well as update
- // the card queue's next index.
- logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION);
- indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION);
- } else {
- g1PostBarrierStub(G1WBPOSTCALL, cardAddress);
- }
- }
- }
- }
- }
-
- private static long getPointerToFirstArrayElement(Address address, int length, int elementStride) {
- long result = Word.fromAddress(address).rawValue();
- if (elementStride < 0) {
- // the address points to the place after the last array element
- result = result + elementStride * length;
- }
- return result;
- }
-
- private static long getPointerToLastArrayElement(Address address, int length, int elementStride) {
- long result = Word.fromAddress(address).rawValue();
- if (elementStride < 0) {
- // the address points to the place after the last array element
- result = result + elementStride;
- } else {
- result = result + (length - 1) * elementStride;
- }
- return result;
- }
-
- public static final ForeignCallDescriptor G1WBPRECALL = new ForeignCallDescriptor("write_barrier_pre", void.class, Object.class);
-
- @NodeIntrinsic(ForeignCallNode.class)
- private static native void g1PreBarrierStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
-
- public static final ForeignCallDescriptor G1WBPOSTCALL = new ForeignCallDescriptor("write_barrier_post", void.class, Word.class);
-
- @NodeIntrinsic(ForeignCallNode.class)
- public static native void g1PostBarrierStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word card);
-
- public static class Templates extends AbstractTemplates {
-
- private final SnippetInfo serialImpreciseWriteBarrier = snippet(WriteBarrierSnippets.class, "serialImpreciseWriteBarrier", GC_CARD_LOCATION);
- private final SnippetInfo serialPreciseWriteBarrier = snippet(WriteBarrierSnippets.class, "serialPreciseWriteBarrier", GC_CARD_LOCATION);
- private final SnippetInfo serialArrayRangeWriteBarrier = snippet(WriteBarrierSnippets.class, "serialArrayRangeWriteBarrier");
- private final SnippetInfo g1PreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
- private final SnippetInfo g1ReferentReadBarrier = g1PreWriteBarrier;
- private final SnippetInfo g1PostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1PostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION);
- private final SnippetInfo g1ArrayRangePreWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePreWriteBarrier", GC_INDEX_LOCATION, GC_LOG_LOCATION);
- private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION);
-
- private final CompressEncoding oopEncoding;
- private final Counters counters;
- private final boolean verifyBarrier;
- private final long gcTotalCollectionsAddress;
-
- public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target,
- GraalHotSpotVMConfig config) {
- super(options, factories, providers, providers.getSnippetReflection(), target);
- this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null;
- this.verifyBarrier = ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC;
- this.gcTotalCollectionsAddress = config.gcTotalCollectionsAddress();
- this.counters = new Counters(factory);
- }
-
- public boolean traceBarrier(StructuredGraph graph) {
- long startCycle = GraalOptions.GCDebugStartCycle.getValue(graph.getOptions());
- return startCycle > 0 && ((Pointer) WordFactory.pointer(gcTotalCollectionsAddress)).readLong(0) > startCycle;
- }
-
- public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) {
- Arguments args;
- if (writeBarrier.usePrecise()) {
- args = new Arguments(serialPreciseWriteBarrier, writeBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- args.add("address", writeBarrier.getAddress());
- } else {
- args = new Arguments(serialImpreciseWriteBarrier, writeBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- OffsetAddressNode address = (OffsetAddressNode) writeBarrier.getAddress();
- args.add("object", address.getBase());
- args.addConst("verifyBarrier", verifyBarrier);
- }
- args.addConst("counters", counters);
- template(writeBarrier, args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args);
- }
-
- public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, LoweringTool tool) {
- Arguments args = new Arguments(serialArrayRangeWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- args.add("address", arrayRangeWriteBarrier.getAddress());
- args.add("length", arrayRangeWriteBarrier.getLength());
- args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
- template(arrayRangeWriteBarrier, args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
- }
-
- public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) {
- Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage(), tool.getLoweringStage());
- AddressNode address = writeBarrierPre.getAddress();
- args.add("address", address);
- if (address instanceof OffsetAddressNode) {
- args.add("object", ((OffsetAddressNode) address).getBase());
- } else {
- args.add("object", null);
- }
-
- ValueNode expected = writeBarrierPre.getExpectedObject();
- if (expected != null && expected.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) {
- assert oopEncoding != null;
- expected = HotSpotCompressionNode.uncompress(expected, oopEncoding);
- }
- args.add("expectedObject", expected);
-
- args.addConst("doLoad", writeBarrierPre.doLoad());
- args.addConst("nullCheck", writeBarrierPre.getNullCheck());
- args.addConst("threadRegister", registers.getThreadRegister());
- args.addConst("trace", traceBarrier(writeBarrierPre.graph()));
- args.addConst("counters", counters);
- template(writeBarrierPre, args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args);
- }
-
- public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
- Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- AddressNode address = readBarrier.getAddress();
- args.add("address", address);
- if (address instanceof OffsetAddressNode) {
- args.add("object", ((OffsetAddressNode) address).getBase());
- } else {
- args.add("object", null);
- }
-
- ValueNode expected = readBarrier.getExpectedObject();
- if (expected != null && expected.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) {
- assert oopEncoding != null;
- expected = HotSpotCompressionNode.uncompress(expected, oopEncoding);
- }
-
- args.add("expectedObject", expected);
- args.addConst("doLoad", readBarrier.doLoad());
- args.addConst("nullCheck", false);
- args.addConst("threadRegister", registers.getThreadRegister());
- args.addConst("trace", traceBarrier(readBarrier.graph()));
- args.addConst("counters", counters);
- template(readBarrier, args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args);
- }
-
- public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers, LoweringTool tool) {
- StructuredGraph graph = writeBarrierPost.graph();
- if (writeBarrierPost.alwaysNull()) {
- graph.removeFixed(writeBarrierPost);
- return;
- }
- Arguments args = new Arguments(g1PostWriteBarrier, graph.getGuardsStage(), tool.getLoweringStage());
- AddressNode address = writeBarrierPost.getAddress();
- args.add("address", address);
- if (address instanceof OffsetAddressNode) {
- args.add("object", ((OffsetAddressNode) address).getBase());
- } else {
- assert writeBarrierPost.usePrecise() : "found imprecise barrier that's not an object access " + writeBarrierPost;
- args.add("object", null);
- }
-
- ValueNode value = writeBarrierPost.getValue();
- if (value.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) {
- assert oopEncoding != null;
- value = HotSpotCompressionNode.uncompress(value, oopEncoding);
- }
- args.add("value", value);
-
- args.addConst("usePrecise", writeBarrierPost.usePrecise());
- args.addConst("verifyBarrier", verifyBarrier);
- args.addConst("threadRegister", registers.getThreadRegister());
- args.addConst("trace", traceBarrier(writeBarrierPost.graph()));
- args.addConst("counters", counters);
- template(writeBarrierPost, args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args);
- }
-
- public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
- Arguments args = new Arguments(g1ArrayRangePreWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- args.add("address", arrayRangeWriteBarrier.getAddress());
- args.add("length", arrayRangeWriteBarrier.getLength());
- args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
- args.addConst("threadRegister", registers.getThreadRegister());
- template(arrayRangeWriteBarrier, args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
- }
-
- public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
- Arguments args = new Arguments(g1ArrayRangePostWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage());
- args.add("address", arrayRangeWriteBarrier.getAddress());
- args.add("length", arrayRangeWriteBarrier.getLength());
- args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
- args.addConst("threadRegister", registers.getThreadRegister());
- template(arrayRangeWriteBarrier, args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
- }
- }
-
- /**
- * Log method of debugging purposes.
- */
- public static void log(boolean enabled, String format, long value) {
- if (enabled) {
- Log.printf(format, value);
- }
- }
-
- public static void log(boolean enabled, String format, long value1, long value2) {
- if (enabled) {
- Log.printf(format, value1, value2);
- }
- }
-
- public static void log(boolean enabled, String format, long value1, long value2, long value3) {
- if (enabled) {
- Log.printf(format, value1, value2, value3);
- }
- }
-
- /**
- * Validation helper method which performs sanity checks on write operations. The addresses of
- * both the object and the value being written are checked in order to determine if they reside
- * in a valid heap region. If an object is stale, an invalid access is performed in order to
- * prematurely crash the VM and debug the stack trace of the faulty method.
- */
- public static void validateObject(Object parent, Object child) {
- if (verifyOops(INJECTED_VMCONFIG) && child != null) {
- Word parentWord = Word.objectToTrackedPointer(parent);
- Word childWord = Word.objectToTrackedPointer(child);
- if (!validateOop(VALIDATE_OBJECT, parentWord, childWord)) {
- log(true, "Verification ERROR, Parent: %p Child: %p\n", parentWord.rawValue(), childWord.rawValue());
- VMErrorNode.vmError("Verification ERROR, Parent: %p\n", parentWord.rawValue());
- }
- }
- }
-
- public static final ForeignCallDescriptor VALIDATE_OBJECT = new ForeignCallDescriptor("validate_object", boolean.class, Word.class, Word.class);
-
- @NodeIntrinsic(ForeignCallNode.class)
- private static native boolean validateOop(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word parent, Word object);
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java Fri Jun 28 14:36:42 2019 +0530
@@ -48,7 +48,7 @@
}
// JDK-8201593: Print array length in ArrayIndexOutOfBoundsException.
- private static final boolean PRINT_LENGTH_IN_EXCEPTION = JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 11;
+ private static final boolean PRINT_LENGTH_IN_EXCEPTION = JavaVersionUtil.JAVA_SPEC >= 11;
private static final int MAX_INT_STRING_SIZE = Integer.toString(Integer.MIN_VALUE).length();
private static final String STR_INDEX = "Index ";
private static final String STR_OUTOFBOUNDSFORLENGTH = " out of bounds for length ";
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java Fri Jun 28 14:36:42 2019 +0530
@@ -42,7 +42,6 @@
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.RemoveValueProxyPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.replacements.SnippetTemplate;
import org.graalvm.compiler.replacements.Snippets;
@@ -104,9 +103,8 @@
new RemoveValueProxyPhase().apply(graph);
graph.setGuardsStage(GuardsStage.FLOATING_GUARDS);
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
- PhaseContext context = new PhaseContext(providers);
- canonicalizer.apply(graph, context);
- new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+ canonicalizer.apply(graph, providers);
+ new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, providers);
} catch (Throwable e) {
throw debug.handle(e);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Fri Jun 28 14:36:42 2019 +0530
@@ -39,7 +39,7 @@
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
import org.graalvm.compiler.hotspot.nodes.VMErrorNode;
-import org.graalvm.compiler.replacements.Log;
+import org.graalvm.compiler.hotspot.replacements.Log;
import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.WordFactory;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,7 +35,6 @@
import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
-import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved;
import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
@@ -256,8 +255,6 @@
import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel;
import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing;
import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins;
-import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_FAST_PATH_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LUDICROUSLY_SLOW_PATH_PROBABILITY;
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING;
@@ -288,6 +285,7 @@
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.PermanentBailoutException;
+import org.graalvm.compiler.core.common.RetryableBailoutException;
import org.graalvm.compiler.core.common.calc.CanonicalCondition;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
@@ -355,6 +353,7 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.UnwindNode;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.ValuePhiNode;
import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.calc.AndNode;
import org.graalvm.compiler.nodes.calc.CompareNode;
@@ -390,7 +389,6 @@
import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode;
import org.graalvm.compiler.nodes.extended.LoadHubNode;
-import org.graalvm.compiler.nodes.extended.LoadMethodNode;
import org.graalvm.compiler.nodes.extended.MembarNode;
import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
@@ -449,7 +447,6 @@
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.JavaTypeProfile;
-import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
import jdk.vm.ci.meta.LineNumberTable;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ProfilingInfo;
@@ -627,7 +624,8 @@
}
static class IntrinsicScope extends InliningScope {
- boolean sawInvalidFrameState;
+ StateSplit returnStateSplit;
+ ArrayList<StateSplit> invalidStateUsers;
IntrinsicScope(BytecodeParser parser) {
super(parser);
@@ -650,30 +648,64 @@
isRootCompilation = false;
}
processPlaceholderFrameStates(isRootCompilation);
- if (sawInvalidFrameState) {
+ if (invalidStateUsers != null) {
JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
- FrameStateBuilder frameStateBuilder = parser.frameState;
- ValueNode returnValue = frameStateBuilder.pop(returnKind);
- StructuredGraph graph = parser.lastInstr.graph();
- StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue));
- parser.lastInstr.setNext(proxy);
- frameStateBuilder.push(returnKind, proxy);
- proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy));
- parser.lastInstr = proxy;
+ ValueNode returnValue = parser.frameState.pop(returnKind);
+ if (invalidStateUsers.size() == 1 && invalidStateUsers.get(0) == parser.lastInstr) {
+ updateSplitFrameState(invalidStateUsers.get(0), returnKind, returnValue);
+ } else if (parser.lastInstr instanceof MergeNode) {
+ ValuePhiNode returnValues = null;
+ MergeNode merge = (MergeNode) parser.lastInstr;
+
+ if (returnValue instanceof ValuePhiNode && ((ValuePhiNode) returnValue).merge() == parser.lastInstr) {
+ returnValues = (ValuePhiNode) returnValue;
+ }
+ if (invalidStateUsers.remove(merge)) {
+ updateSplitFrameState(merge, returnKind, returnValue);
+ }
+ for (EndNode pred : merge.cfgPredecessors()) {
+ Node lastPred = pred.predecessor();
+ if (invalidStateUsers.remove(lastPred)) {
+ ValueNode predReturnValue = returnValue;
+ if (returnValues != null) {
+ int index = merge.phiPredecessorIndex(pred);
+ predReturnValue = ((ValuePhiNode) returnValue).valueAt(index);
+ }
+ updateSplitFrameState((StateSplit) lastPred, returnKind, predReturnValue);
+ }
+ }
+ if (invalidStateUsers.size() != 0) {
+ throw new GraalError("unexpected StateSplit above merge %s", invalidStateUsers);
+ }
+ } else {
+ throw new GraalError("unexpected node between return StateSplit and last instruction %s", parser.lastInstr);
+ }
+ // Restore the original return value
+ parser.frameState.push(returnKind, returnValue);
+ }
+ }
+
+ private void updateSplitFrameState(StateSplit split, JavaKind returnKind, ValueNode returnValue) {
+ parser.frameState.push(returnKind, returnValue);
+ FrameState oldState = split.stateAfter();
+ split.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), split));
+ parser.frameState.pop(returnKind);
+ if (oldState.hasNoUsages()) {
+ oldState.safeDelete();
}
}
@Override
protected void handleReturnMismatch(StructuredGraph g, FrameState fs) {
- // If the intrinsic returns a non-void value, then any frame
- // state with an empty stack is invalid as it cannot
- // be used to deoptimize to just after the call returns.
- // These invalid frame states are expected to be removed
- // by later compilation stages.
- FrameState newFrameState = g.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
- newFrameState.setNodeSourcePosition(fs.getNodeSourcePosition());
- fs.replaceAndDelete(newFrameState);
- sawInvalidFrameState = true;
+ if (invalidStateUsers == null) {
+ invalidStateUsers = new ArrayList<>();
+ }
+ for (Node use : fs.usages()) {
+ if (!(use instanceof StateSplit)) {
+ throw new GraalError("Expected StateSplit for return mismatch");
+ }
+ invalidStateUsers.add((StateSplit) use);
+ }
}
}
@@ -999,6 +1031,11 @@
beginNode.safeDelete();
}
}
+ if (graph.isOSR() && getParent() == null && graph.getNodes().filter(EntryMarkerNode.class).isEmpty()) {
+ // This should generally be a transient condition because of inconsistent profile
+ // information.
+ throw new RetryableBailoutException("OSR entry point wasn't parsed");
+ }
}
/**
@@ -1734,10 +1771,7 @@
return null;
}
- JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass());
- if (graphBuilderConfig.eagerResolving() || parsingIntrinsic()) {
- returnType = returnType.resolve(targetMethod.getDeclaringClass());
- }
+ JavaType returnType = maybeEagerlyResolve(targetMethod.getSignature().getReturnType(method.getDeclaringClass()), targetMethod.getDeclaringClass());
if (invokeKind.hasReceiver()) {
args[0] = maybeEmitExplicitNullCheck(args[0]);
}
@@ -1763,8 +1797,8 @@
return null;
}
- if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) {
- if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) {
+ if (!invokeKind.isIndirect()) {
+ if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType)) {
if (TraceParserPlugins.getValue(options)) {
traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
}
@@ -2040,184 +2074,8 @@
}
}
- protected static class IntrinsicGuard {
- final FixedWithNextNode lastInstr;
- final Mark mark;
- final AbstractBeginNode nonIntrinsicBranch;
- final ValueNode receiver;
- final JavaTypeProfile profile;
-
- public IntrinsicGuard(FixedWithNextNode lastInstr, ValueNode receiver, Mark mark, AbstractBeginNode nonIntrinsicBranch, JavaTypeProfile profile) {
- this.lastInstr = lastInstr;
- this.receiver = receiver;
- this.mark = mark;
- this.nonIntrinsicBranch = nonIntrinsicBranch;
- this.profile = profile;
- }
- }
-
- /**
- * Weaves a test of the receiver type to ensure the dispatch will select {@code targetMethod}
- * and not another method that overrides it. This should only be called if there is an
- * {@link InvocationPlugin} for {@code targetMethod} and the invocation is indirect.
- *
- * The control flow woven around the intrinsic is as follows:
- *
- * <pre>
- * if (LoadMethod(LoadHub(receiver)) == targetMethod) {
- * <intrinsic for targetMethod>
- * } else {
- * <virtual call to targetMethod>
- * }
- * </pre>
- *
- * The {@code else} branch is woven by {@link #afterInvocationPluginExecution}.
- *
- * @return {@code null} if the intrinsic cannot be used otherwise an object to be used by
- * {@link #afterInvocationPluginExecution} to weave code for the non-intrinsic branch
- */
- protected IntrinsicGuard guardIntrinsic(ValueNode[] args, ResolvedJavaMethod targetMethod, InvocationPluginReceiver pluginReceiver) {
- ValueNode intrinsicReceiver = args[0];
- ResolvedJavaType receiverType = StampTool.typeOrNull(intrinsicReceiver);
- if (receiverType == null) {
- // The verifier guarantees it to be at least type declaring targetMethod
- receiverType = targetMethod.getDeclaringClass();
- }
- ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
- if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
- assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
- Mark mark = graph.getMark();
- FixedWithNextNode currentLastInstr = lastInstr;
- ValueNode nonNullReceiver = pluginReceiver.get();
- Stamp methodStamp = getStampProvider().createMethodStamp();
- LoadHubNode hub = graph.unique(new LoadHubNode(getStampProvider(), nonNullReceiver));
- LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
- ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
- LogicNode compare = graph.addOrUniqueWithInputs(
- CompareNode.createCompareNode(getConstantReflection(), getMetaAccess(), options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT));
-
- JavaTypeProfile profile = null;
- if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
- profile = profilingInfo.getTypeProfile(bci());
- if (profile != null) {
- JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
- if (newProfile != profile) {
- if (newProfile.getTypes().length == 0) {
- // All profiled types select the intrinsic so
- // emit a fixed guard instead of an if-then-else.
- lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
- return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
- }
- } else {
- // No profiled types select the intrinsic so emit a virtual call
- return null;
- }
- profile = newProfile;
- }
- }
-
- AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
- AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
- // In the adjustment above, we filter out receiver types that select the intrinsic as
- // virtual call target. This means the recorded types in the adjusted profile will
- // definitely not call into the intrinsic. Note that the following branch probability is
- // still not precise -- the previously-not-recorded receiver types in the original
- // profile might or might not call into the intrinsic. Yet we accumulate them into the
- // probability of the intrinsic branch, assuming that the not-recorded types will only
- // be a small fraction.
- append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, profile != null ? profile.getNotRecordedProbability() : LIKELY_PROBABILITY));
- lastInstr = intrinsicBranch;
- return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
- } else {
- // Receiver selects an overriding method so emit a virtual call
- return null;
- }
- }
-
- /**
- * Adjusts the profile for an indirect invocation of a virtual method for which there is an
- * intrinsic. The adjustment made by this method is to remove all types from the profile that do
- * not override {@code targetMethod}.
- *
- * @param profile the profile to adjust
- * @param targetMethod the virtual method for which there is an intrinsic
- * @return the adjusted profile or the original {@code profile} object if no adjustment was made
- */
- protected JavaTypeProfile adjustProfileForInvocationPlugin(JavaTypeProfile profile, ResolvedJavaMethod targetMethod) {
- if (profile.getTypes().length > 0) {
- List<ProfiledType> retained = new ArrayList<>();
- double notRecordedProbability = profile.getNotRecordedProbability();
- for (ProfiledType ptype : profile.getTypes()) {
- if (!ptype.getType().resolveMethod(targetMethod, method.getDeclaringClass()).equals(targetMethod)) {
- retained.add(ptype);
- } else {
- notRecordedProbability += ptype.getProbability();
- }
- }
- if (!retained.isEmpty()) {
- if (retained.size() != profile.getTypes().length) {
- return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, retained.toArray(new ProfiledType[retained.size()]));
- }
- } else {
- return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, new ProfiledType[0]);
- }
- }
- return profile;
- }
-
- /**
- * Performs any action required after execution of an invocation plugin. This includes
- * {@linkplain InvocationPluginAssertions#check checking} invocation plugin invariants as well
- * as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if
- * {@code guard != null}.
- */
- protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard,
- InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
- assert assertions.check(pluginHandledInvoke);
- if (intrinsicGuard != null) {
- if (pluginHandledInvoke) {
- if (intrinsicGuard.nonIntrinsicBranch != null) {
- // Intrinsic emitted: emit a virtual call to the target method and
- // merge it with the intrinsic branch
- EndNode intrinsicEnd = append(new EndNode());
-
- FrameStateBuilder intrinsicState = null;
- FrameStateBuilder nonIntrinisicState = null;
- if (resultType != JavaKind.Void) {
- intrinsicState = frameState.copy();
- frameState.pop(resultType);
- nonIntrinisicState = frameState;
- }
-
- lastInstr = intrinsicGuard.nonIntrinsicBranch;
- createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
-
- EndNode nonIntrinsicEnd = append(new EndNode());
- AbstractMergeNode mergeNode = graph.add(new MergeNode());
-
- mergeNode.addForwardEnd(intrinsicEnd);
- if (intrinsicState != null) {
- intrinsicState.merge(mergeNode, nonIntrinisicState);
- frameState = intrinsicState;
- }
- mergeNode.addForwardEnd(nonIntrinsicEnd);
- mergeNode.setStateAfter(frameState.create(stream.nextBCI(), mergeNode));
-
- lastInstr = mergeNode;
- }
- } else {
- // Intrinsic was not applied: remove intrinsic guard
- // and restore the original receiver node in the arguments array
- intrinsicGuard.lastInstr.setNext(null);
- GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
- lastInstr = intrinsicGuard.lastInstr;
- args[0] = intrinsicGuard.receiver;
- }
- }
- }
-
@SuppressWarnings("try")
- protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
+ protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
if (plugin != null) {
@@ -2227,24 +2085,15 @@
}
InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args);
-
- IntrinsicGuard intrinsicGuard = null;
- if (invokeKind.isIndirect()) {
- intrinsicGuard = guardIntrinsic(args, targetMethod, pluginReceiver);
- if (intrinsicGuard == null) {
- return false;
- } else if (intrinsicGuard.nonIntrinsicBranch == null) {
- assert lastInstr instanceof FixedGuardNode;
- }
- }
+ assert invokeKind.isDirect() : "Cannot apply invocation plugin on an indirect call site.";
InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
try (DebugCloseable context = openNodeContext(targetMethod)) {
if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
- afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
+ assert assertions.check(true);
return !plugin.isDecorator();
} else {
- afterInvocationPluginExecution(false, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
+ assert assertions.check(false);
}
}
}
@@ -2630,8 +2479,9 @@
FixedWithNextNode calleeBeforeUnwindNode = null;
ValueNode calleeUnwindValue = null;
- try (InliningScope s = parsingIntrinsic() ? null : (calleeIntrinsicContext != null ? new IntrinsicScope(this, targetMethod, args)
- : new InliningScope(this, targetMethod, args))) {
+ try (InliningScope s = parsingIntrinsic() ? null
+ : (calleeIntrinsicContext != null ? new IntrinsicScope(this, targetMethod, args)
+ : new InliningScope(this, targetMethod, args))) {
BytecodeParser parser = graphBuilderInstance.createBytecodeParser(graph, this, targetMethod, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
FrameStateBuilder startFrameState = new FrameStateBuilder(parser, parser.code, graph, graphBuilderConfig.retainLocalVariables());
if (!targetMethod.isStatic()) {
@@ -2642,7 +2492,6 @@
List<ReturnToCallerData> calleeReturnDataList = parser.returnDataList;
- processCalleeReturn(targetMethod, s, calleeReturnDataList);
/*
* Propagate any side effects into the caller when parsing intrinsics.
*/
@@ -2652,6 +2501,8 @@
}
}
+ processCalleeReturn(targetMethod, s, calleeReturnDataList);
+
calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
if (calleeBeforeUnwindNode != null) {
calleeUnwindValue = parser.getUnwindValue();
@@ -2743,7 +2594,7 @@
if (stateSplit.hasSideEffect()) {
assert stateSplit != null;
if (stateAfter.bci == BytecodeFrame.AFTER_BCI) {
- assert stateAfter.usages().count() == 1;
+ assert stateAfter.hasExactlyOneUsage();
assert stateAfter.usages().first() == stateSplit;
FrameState state;
if (returnVal.getStackKind() == JavaKind.Illegal) {
@@ -4233,7 +4084,7 @@
private String unresolvedMethodAssertionMessage(JavaMethod result) {
String message = result.format("%H.%n(%P)%R");
- if (JavaVersionUtil.Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
JavaType declaringClass = result.getDeclaringClass();
String className = declaringClass.getName();
switch (className) {
@@ -4324,6 +4175,13 @@
}
}
+ protected JavaType maybeEagerlyResolve(JavaType type, ResolvedJavaType accessingClass) {
+ if (graphBuilderConfig.eagerResolving() || parsingIntrinsic()) {
+ return type.resolve(accessingClass);
+ }
+ return type;
+ }
+
protected void maybeEagerlyInitialize(ResolvedJavaType resolvedType) {
if (!resolvedType.isInitialized() && eagerInitializing) {
initialize(resolvedType);
@@ -5350,4 +5208,3 @@
return n == 0 ? "" : format("%" + n + "s", "");
}
}
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,8 +66,5 @@
@Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug)
public static final OptionKey<Boolean> HideSubstitutionStates = new OptionKey<>(false);
-
- @Option(help = "Use intrinsics guarded by a virtual dispatch test at indirect call sites.", type = OptionType.Debug)
- public static final OptionKey<Boolean> UseGuardedIntrinsics = new OptionKey<>(true);
// @formatter:on
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,7 +43,6 @@
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
-import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
@@ -146,7 +145,7 @@
this.monitorIds = EMPTY_MONITOR_ARRAY;
this.graph = graph;
- this.clearNonLiveLocals = GraalOptions.OptClearNonLiveLocals.getValue(graph.getOptions()) && !shouldRetainLocalVariables;
+ this.clearNonLiveLocals = !shouldRetainLocalVariables;
this.canVerifyKind = true;
}
@@ -275,8 +274,6 @@
clearNonLiveLocals = other.clearNonLiveLocals;
monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone();
- assert locals.length == code.getMaxLocals();
- assert stack.length == Math.max(1, code.getMaxStackSize());
assert lockedObjects.length == monitorIds.length;
}
@@ -791,7 +788,7 @@
public ValueNode pop(JavaKind slotKind) {
if (slotKind.needsTwoSlots()) {
ValueNode s = xpop();
- assert s == TWO_SLOT_MARKER;
+ assert s == TWO_SLOT_MARKER : s;
}
ValueNode x = xpop();
assert verifyKind(slotKind, x);
@@ -835,7 +832,7 @@
/* Ignore second slot of two-slot value. */
x = xpop();
}
- assert x != null && x != TWO_SLOT_MARKER;
+ assert x != null && x != TWO_SLOT_MARKER : x;
result[i] = x;
}
return result;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,6 +26,7 @@
import org.graalvm.compiler.jtt.JTTTest;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -37,7 +38,7 @@
* Tests a unary {@link Math} method on a wide range of values.
*/
void testManyValues(OptionValues options, ResolvedJavaMethod method) throws AssertionError {
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
/*
* GR-8276: Allow for variance on JVMCI > 8 until a JVMCI version that includes
* https://github.com/graalvm/graal-jvmci-8/commit/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java Fri Jun 28 14:36:42 2019 +0530
@@ -129,8 +129,7 @@
}
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
+ protected void checkHighTierGraph(StructuredGraph graph) {
assert graph.getNodes().filter(CommitAllocationNode.class).count() == 0 : "all allocations should be virtualized";
- return true;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/TrichotomyFloats.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.jtt.optimize;
+
+import org.junit.Test;
+
+import org.graalvm.compiler.jtt.JTTTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/*
+ * Tests comparison-based canonicalizations for floats.
+ */
+@RunWith(Parameterized.class)
+public class TrichotomyFloats extends JTTTest {
+
+ public static int test0(float x, float y) {
+ return x < y ? -1 : (x == y ? 0 : 1);
+ }
+
+ public static int test1(float x, float y) {
+ return x < y ? 1 : (x == y ? 0 : -1);
+ }
+
+ public static int test2(float x, float y) {
+ return x == y ? 0 : (x < y ? -1 : 1);
+ }
+
+ public static int test3(float x, float y) {
+ return x == y ? 0 : (x < y ? 1 : -1);
+ }
+
+ public static int test4(float x, float y) {
+ return x == y ? 0 : (x > y ? -1 : 1);
+ }
+
+ public static int test5(float x, float y) {
+ return x == y ? 0 : (x > y ? 1 : -1);
+ }
+
+ public static int test6(float x, float y) {
+ return x < y ? 1 : (x > y ? -1 : 0);
+ }
+
+ public static int test7(float x, float y) {
+ return x < y ? -1 : (x > y ? 1 : 0);
+ }
+
+ @Parameter(value = 0) public float x;
+ @Parameter(value = 1) public float y;
+
+ @Parameters(name = "x = {0}, y = {1}")
+ public static Collection<Object[]> data() {
+ List<Object[]> parameters = new ArrayList<>();
+ float[] floats = {Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.NaN, 0f, -1f, Float.MIN_VALUE, Float.MAX_VALUE};
+ for (float f1 : floats) {
+ for (float f2 : floats) {
+ parameters.add(new Object[]{f1, f2});
+ }
+ }
+ return parameters;
+ }
+
+ @Test
+ public void run0() {
+ runTest("test0", x, y);
+ }
+
+ @Test
+ public void run1() {
+ runTest("test1", x, y);
+ }
+
+ @Test
+ public void run2() {
+ runTest("test2", x, y);
+ }
+
+ @Test
+ public void run3() {
+ runTest("test3", x, y);
+ }
+
+ @Test
+ public void run4() {
+ runTest("test4", x, y);
+ }
+
+ @Test
+ public void run5() {
+ runTest("test5", x, y);
+ }
+
+ @Test
+ public void run6() {
+ runTest("test6", x, y);
+ }
+
+ @Test
+ public void run7() {
+ runTest("test7", x, y);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitFieldOp.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited and affiliates. All rights reserved.
+ * 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 org.graalvm.compiler.lir.aarch64;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.AllocatableValue;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+
+/**
+ * Bit field ops for AArch64.
+ */
+public class AArch64BitFieldOp extends AArch64LIRInstruction {
+ public enum BitFieldOpCode {
+ UBFX,
+ UBFIZ,
+ }
+
+ private static final LIRInstructionClass<AArch64BitFieldOp> TYPE = LIRInstructionClass.create(AArch64BitFieldOp.class);
+
+ @Opcode private final AArch64BitFieldOp.BitFieldOpCode opcode;
+ @Def protected AllocatableValue result;
+ @Use({REG}) protected AllocatableValue input;
+ private final int lsb;
+ private final int width;
+
+ public AArch64BitFieldOp(AArch64BitFieldOp.BitFieldOpCode opcode, AllocatableValue result,
+ AllocatableValue input, int lsb, int width) {
+ super(TYPE);
+ this.opcode = opcode;
+ this.result = result;
+ this.input = input;
+ this.lsb = lsb;
+ this.width = width;
+ }
+
+ @Override
+ protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
+ Register dst = asRegister(result);
+ Register src = asRegister(input);
+ final int size = input.getPlatformKind().getSizeInBytes() * Byte.SIZE;
+ switch (opcode) {
+ case UBFX:
+ masm.ubfm(size, dst, src, lsb, lsb + width - 1);
+ break;
+ case UBFIZ:
+ masm.ubfm(size, dst, src, size - lsb, width - 1);
+ break;
+ default:
+ throw GraalError.shouldNotReachHere();
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Fri Jun 28 14:36:42 2019 +0530
@@ -433,7 +433,10 @@
}
static void reg2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) {
- AArch64Address dest = loadStackSlotAddress(crb, masm, asStackSlot(result), Value.ILLEGAL);
+ AArch64Address dest;
+ try (ScratchRegister scratch = masm.getScratchRegister()) {
+ dest = loadStackSlotAddress(crb, masm, asStackSlot(result), scratch.getRegister());
+ }
Register src = asRegister(input);
// use the slot kind to define the operand size
AArch64Kind kind = (AArch64Kind) result.getPlatformKind();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Fri Jun 28 14:36:42 2019 +0530
@@ -48,6 +48,7 @@
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.XOR;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
@@ -79,10 +80,10 @@
@Alive({REG}) private Value array1Value;
@Alive({REG}) private Value array2Value;
@Alive({REG}) private Value lengthValue;
- @Temp({REG}) private Value temp1;
- @Temp({REG}) private Value temp2;
+ @Temp({REG, ILLEGAL}) private Value temp1;
+ @Temp({REG, ILLEGAL}) private Value temp2;
@Temp({REG}) private Value temp3;
- @Temp({REG}) private Value temp4;
+ @Temp({REG, ILLEGAL}) private Value temp4;
@Temp({REG, ILLEGAL}) private Value temp5;
@Temp({REG, ILLEGAL}) private Value tempXMM;
@@ -114,12 +115,22 @@
this.lengthValue = length;
// Allocate some temporaries.
- this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
- this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+ if (supportsSSE41(tool.target()) && canGenerateConstantLengthCompare(tool.target()) && !constantLengthCompareNeedsTmpArrayPointers()) {
+ this.temp1 = Value.ILLEGAL;
+ this.temp2 = Value.ILLEGAL;
+ } else {
+ this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+ this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+ }
this.temp3 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind()));
- this.temp4 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind()));
+ if (supportsSSE41(tool.target()) && canGenerateConstantLengthCompare(tool.target())) {
+ this.temp4 = Value.ILLEGAL;
+ this.temp5 = Value.ILLEGAL;
+ } else {
+ this.temp4 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind()));
+ this.temp5 = kind1.isNumericFloat() || kind1 != kind2 ? tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())) : Value.ILLEGAL;
+ }
- this.temp5 = kind1.isNumericFloat() || kind1 != kind2 ? tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())) : Value.ILLEGAL;
if (kind1 == JavaKind.Float) {
this.tempXMM = tool.newVariable(LIRKind.value(AMD64Kind.SINGLE));
} else if (kind1 == JavaKind.Double) {
@@ -157,21 +168,19 @@
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
Register result = asRegister(resultValue);
- Register array1 = asRegister(temp1);
- Register array2 = asRegister(temp2);
Label trueLabel = new Label();
Label falseLabel = new Label();
Label done = new Label();
- // Load array base addresses.
- masm.leaq(array1, new AMD64Address(asRegister(array1Value), arrayBaseOffset1));
- masm.leaq(array2, new AMD64Address(asRegister(array2Value), arrayBaseOffset2));
-
if (canGenerateConstantLengthCompare(crb.target)) {
- emitConstantLengthArrayCompareBytes(crb, masm, array1, array2, asRegister(temp3), asRegister(temp4),
- new Register[]{asRegister(vectorTemp1), asRegister(vectorTemp2), asRegister(vectorTemp3), asRegister(vectorTemp4)}, falseLabel);
+ emitConstantLengthArrayCompareBytes(crb, masm, new Register[]{asRegister(vectorTemp1), asRegister(vectorTemp2), asRegister(vectorTemp3), asRegister(vectorTemp4)}, falseLabel);
} else {
+ Register array1 = asRegister(temp1);
+ Register array2 = asRegister(temp2);
+ // Load array base addresses.
+ masm.leaq(array1, new AMD64Address(asRegister(array1Value), arrayBaseOffset1));
+ masm.leaq(array2, new AMD64Address(asRegister(array2Value), arrayBaseOffset2));
Register length = asRegister(temp3);
// Get array length.
masm.movl(length, asRegister(lengthValue));
@@ -705,6 +714,15 @@
masm.subq(index, range);
}
+ private boolean constantLengthCompareNeedsTmpArrayPointers() {
+ AVXKind.AVXSize vSize = vectorSize;
+ if (constantLength < getElementsPerVector(vectorSize)) {
+ vSize = AVXKind.AVXSize.XMM;
+ }
+ int vectorCount = constantLength & ~(2 * getElementsPerVector(vSize) - 1);
+ return vectorCount > 0;
+ }
+
/**
* Emits specialized assembly for checking equality of memory regions
* {@code arrayPtr1[0..nBytes]} and {@code arrayPtr2[0..nBytes]}. If they match, execution
@@ -713,16 +731,15 @@
private void emitConstantLengthArrayCompareBytes(
CompilationResultBuilder crb,
AMD64MacroAssembler asm,
- Register arrayPtr1,
- Register arrayPtr2,
- Register tmp1,
- Register tmp2,
Register[] tmpVectors,
Label noMatch) {
if (constantLength == 0) {
// do nothing
return;
}
+ Register arrayPtr1 = asRegister(array1Value);
+ Register arrayPtr2 = asRegister(array2Value);
+ Register tmp = asRegister(temp3);
AVXKind.AVXSize vSize = vectorSize;
if (constantLength < getElementsPerVector(vectorSize)) {
vSize = AVXKind.AVXSize.XMM;
@@ -731,17 +748,15 @@
if (elementsPerVector > constantLength) {
assert kind1 == kind2;
int byteLength = constantLength << arrayIndexScale1.log2;
- // array is shorter than any vector register, use regular CMP instructions
+ // array is shorter than any vector register, use regular XOR instructions
int movSize = (byteLength < 2) ? 1 : ((byteLength < 4) ? 2 : ((byteLength < 8) ? 4 : 8));
- emitMovBytes(asm, tmp1, new AMD64Address(arrayPtr1), movSize);
- emitMovBytes(asm, tmp2, new AMD64Address(arrayPtr2), movSize);
- emitCmpBytes(asm, tmp1, tmp2, movSize);
- asm.jcc(AMD64Assembler.ConditionFlag.NotEqual, noMatch);
+ emitMovBytes(asm, tmp, new AMD64Address(arrayPtr1, arrayBaseOffset1), movSize);
+ emitXorBytes(asm, tmp, new AMD64Address(arrayPtr2, arrayBaseOffset2), movSize);
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, noMatch);
if (byteLength > movSize) {
- emitMovBytes(asm, tmp1, new AMD64Address(arrayPtr1, byteLength - movSize), movSize);
- emitMovBytes(asm, tmp2, new AMD64Address(arrayPtr2, byteLength - movSize), movSize);
- emitCmpBytes(asm, tmp1, tmp2, movSize);
- asm.jcc(AMD64Assembler.ConditionFlag.NotEqual, noMatch);
+ emitMovBytes(asm, tmp, new AMD64Address(arrayPtr1, arrayBaseOffset1 + byteLength - movSize), movSize);
+ emitXorBytes(asm, tmp, new AMD64Address(arrayPtr2, arrayBaseOffset2 + byteLength - movSize), movSize);
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, noMatch);
}
} else {
int elementsPerVectorLoop = 2 * elementsPerVector;
@@ -750,37 +765,41 @@
int bytesPerVector = vSize.getBytes();
if (vectorCount > 0) {
Label loopBegin = new Label();
- asm.leaq(arrayPtr1, new AMD64Address(arrayPtr1, vectorCount << arrayIndexScale1.log2));
- asm.leaq(arrayPtr2, new AMD64Address(arrayPtr2, vectorCount << arrayIndexScale2.log2));
- asm.movq(tmp1, -vectorCount);
+ Register tmpArrayPtr1 = asRegister(temp1);
+ Register tmpArrayPtr2 = asRegister(temp2);
+ asm.leaq(tmpArrayPtr1, new AMD64Address(arrayPtr1, vectorCount << arrayIndexScale1.log2));
+ asm.leaq(tmpArrayPtr2, new AMD64Address(arrayPtr2, vectorCount << arrayIndexScale2.log2));
+ arrayPtr1 = tmpArrayPtr1;
+ arrayPtr2 = tmpArrayPtr2;
+ asm.movq(tmp, -vectorCount);
asm.align(crb.target.wordSize * 2);
asm.bind(loopBegin);
- emitVectorLoad1(asm, tmpVectors[0], arrayPtr1, tmp1, 0, vSize);
- emitVectorLoad2(asm, tmpVectors[1], arrayPtr2, tmp1, 0, vSize);
- emitVectorLoad1(asm, tmpVectors[2], arrayPtr1, tmp1, scaleDisplacement1(bytesPerVector), vSize);
- emitVectorLoad2(asm, tmpVectors[3], arrayPtr2, tmp1, scaleDisplacement2(bytesPerVector), vSize);
+ emitVectorLoad1(asm, tmpVectors[0], arrayPtr1, tmp, arrayBaseOffset1, vSize);
+ emitVectorLoad2(asm, tmpVectors[1], arrayPtr2, tmp, arrayBaseOffset2, vSize);
+ emitVectorLoad1(asm, tmpVectors[2], arrayPtr1, tmp, arrayBaseOffset1 + scaleDisplacement1(bytesPerVector), vSize);
+ emitVectorLoad2(asm, tmpVectors[3], arrayPtr2, tmp, arrayBaseOffset2 + scaleDisplacement2(bytesPerVector), vSize);
emitVectorXor(asm, tmpVectors[0], tmpVectors[1], vSize);
emitVectorXor(asm, tmpVectors[2], tmpVectors[3], vSize);
emitVectorTest(asm, tmpVectors[0], vSize);
- asm.jcc(AMD64Assembler.ConditionFlag.NotZero, noMatch);
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, noMatch);
emitVectorTest(asm, tmpVectors[2], vSize);
- asm.jcc(AMD64Assembler.ConditionFlag.NotZero, noMatch);
- asm.addq(tmp1, elementsPerVectorLoop);
- asm.jcc(AMD64Assembler.ConditionFlag.NotZero, loopBegin);
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, noMatch);
+ asm.addq(tmp, elementsPerVectorLoop);
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, loopBegin);
}
if (tailCount > 0) {
- emitVectorLoad1(asm, tmpVectors[0], arrayPtr1, (tailCount << arrayIndexScale1.log2) - scaleDisplacement1(bytesPerVector), vSize);
- emitVectorLoad2(asm, tmpVectors[1], arrayPtr2, (tailCount << arrayIndexScale2.log2) - scaleDisplacement2(bytesPerVector), vSize);
+ emitVectorLoad1(asm, tmpVectors[0], arrayPtr1, arrayBaseOffset1 + (tailCount << arrayIndexScale1.log2) - scaleDisplacement1(bytesPerVector), vSize);
+ emitVectorLoad2(asm, tmpVectors[1], arrayPtr2, arrayBaseOffset2 + (tailCount << arrayIndexScale2.log2) - scaleDisplacement2(bytesPerVector), vSize);
emitVectorXor(asm, tmpVectors[0], tmpVectors[1], vSize);
if (tailCount > elementsPerVector) {
- emitVectorLoad1(asm, tmpVectors[2], arrayPtr1, 0, vSize);
- emitVectorLoad2(asm, tmpVectors[3], arrayPtr2, 0, vSize);
+ emitVectorLoad1(asm, tmpVectors[2], arrayPtr1, arrayBaseOffset1, vSize);
+ emitVectorLoad2(asm, tmpVectors[3], arrayPtr2, arrayBaseOffset2, vSize);
emitVectorXor(asm, tmpVectors[2], tmpVectors[3], vSize);
emitVectorTest(asm, tmpVectors[2], vSize);
- asm.jcc(AMD64Assembler.ConditionFlag.NotZero, noMatch);
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, noMatch);
}
emitVectorTest(asm, tmpVectors[0], vSize);
- asm.jcc(AMD64Assembler.ConditionFlag.NotZero, noMatch);
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, noMatch);
}
}
}
@@ -817,11 +836,23 @@
}
}
- private static void emitCmpBytes(AMD64MacroAssembler asm, Register dst, Register src, int size) {
- if (size < 8) {
- asm.cmpl(dst, src);
- } else {
- asm.cmpq(dst, src);
+ private static void emitXorBytes(AMD64MacroAssembler asm, Register dst, AMD64Address src, int size) {
+ OperandSize opSize = getOperandSize(size);
+ XOR.getRMOpcode(opSize).emit(asm, opSize, dst, src);
+ }
+
+ private static OperandSize getOperandSize(int size) {
+ switch (size) {
+ case 1:
+ return OperandSize.BYTE;
+ case 2:
+ return OperandSize.WORD;
+ case 4:
+ return OperandSize.DWORD;
+ case 8:
+ return OperandSize.QWORD;
+ default:
+ throw new IllegalStateException();
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,30 +24,43 @@
package org.graalvm.compiler.lir.amd64;
-import jdk.vm.ci.amd64.AMD64;
-import jdk.vm.ci.amd64.AMD64.CPUFeature;
-import jdk.vm.ci.amd64.AMD64Kind;
-import jdk.vm.ci.code.Register;
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.Value;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
+
+import java.util.Objects;
+
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.asm.amd64.AMD64Assembler;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexMoveOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
+import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.asm.amd64.AVXKind;
import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.lir.ConstantValue;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
-import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64.CPUFeature;
+import jdk.vm.ci.amd64.AMD64Kind;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
/**
*/
@@ -55,24 +68,23 @@
public final class AMD64ArrayIndexOfOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<AMD64ArrayIndexOfOp> TYPE = LIRInstructionClass.create(AMD64ArrayIndexOfOp.class);
- private final JavaKind kind;
- private final int vmPageSize;
+ private final JavaKind valueKind;
private final int nValues;
private final boolean findTwoConsecutive;
private final AMD64Kind vectorKind;
+ private final int arrayBaseOffset;
+ private final Scale arrayIndexScale;
@Def({REG}) protected Value resultValue;
@Alive({REG}) protected Value arrayPtrValue;
- @Use({REG}) protected Value arrayLengthValue;
- @Alive({REG}) protected Value searchValue1;
- @Alive({REG, ILLEGAL}) protected Value searchValue2;
- @Alive({REG, ILLEGAL}) protected Value searchValue3;
- @Alive({REG, ILLEGAL}) protected Value searchValue4;
- @Temp({REG}) protected Value arraySlotsRemaining;
+ @Alive({REG}) protected Value arrayLengthValue;
+ @Use({REG}) protected Value fromIndexValue;
+ @Alive({REG, STACK, CONST}) protected Value searchValue1;
+ @Alive({REG, STACK, CONST, ILLEGAL}) protected Value searchValue2;
+ @Alive({REG, STACK, CONST, ILLEGAL}) protected Value searchValue3;
+ @Alive({REG, STACK, CONST, ILLEGAL}) protected Value searchValue4;
@Temp({REG}) protected Value comparisonResult1;
- @Temp({REG}) protected Value comparisonResult2;
- @Temp({REG}) protected Value comparisonResult3;
- @Temp({REG}) protected Value comparisonResult4;
+ @Temp({REG, ILLEGAL}) protected Value comparisonResult2;
@Temp({REG, ILLEGAL}) protected Value vectorCompareVal1;
@Temp({REG, ILLEGAL}) protected Value vectorCompareVal2;
@Temp({REG, ILLEGAL}) protected Value vectorCompareVal3;
@@ -82,31 +94,30 @@
@Temp({REG, ILLEGAL}) protected Value vectorArray3;
@Temp({REG, ILLEGAL}) protected Value vectorArray4;
- public AMD64ArrayIndexOfOp(JavaKind kind, boolean findTwoConsecutive, int vmPageSize, int maxVectorSize, LIRGeneratorTool tool, Value result, Value arrayPtr, Value arrayLength,
- Value... searchValues) {
+ public AMD64ArrayIndexOfOp(JavaKind arrayKind, JavaKind valueKind, boolean findTwoConsecutive, int maxVectorSize, LIRGeneratorTool tool,
+ Value result, Value arrayPtr, Value arrayLength, Value fromIndex, Value... searchValues) {
super(TYPE);
- this.kind = kind;
+ this.valueKind = valueKind;
+ this.arrayBaseOffset = tool.getProviders().getMetaAccess().getArrayBaseOffset(arrayKind);
+ this.arrayIndexScale = Objects.requireNonNull(Scale.fromInt(tool.getProviders().getMetaAccess().getArrayIndexScale(valueKind)));
this.findTwoConsecutive = findTwoConsecutive;
- this.vmPageSize = vmPageSize;
assert 0 < searchValues.length && searchValues.length <= 4;
- assert byteMode(kind) || charMode(kind);
+ assert byteMode(valueKind) || charMode(valueKind);
assert supports(tool, CPUFeature.SSE2) || supports(tool, CPUFeature.AVX) || supportsAVX2(tool);
nValues = searchValues.length;
assert !findTwoConsecutive || nValues == 1;
resultValue = result;
arrayPtrValue = arrayPtr;
arrayLengthValue = arrayLength;
+ fromIndexValue = fromIndex;
searchValue1 = searchValues[0];
searchValue2 = nValues > 1 ? searchValues[1] : Value.ILLEGAL;
searchValue3 = nValues > 2 ? searchValues[2] : Value.ILLEGAL;
searchValue4 = nValues > 3 ? searchValues[3] : Value.ILLEGAL;
- arraySlotsRemaining = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
- comparisonResult1 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
- comparisonResult2 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
- comparisonResult3 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
- comparisonResult4 = tool.newVariable(LIRKind.value(AMD64Kind.DWORD));
- vectorKind = supportsAVX2(tool) && (maxVectorSize < 0 || maxVectorSize >= 32) ? byteMode(kind) ? AMD64Kind.V256_BYTE : AMD64Kind.V256_WORD
- : byteMode(kind) ? AMD64Kind.V128_BYTE : AMD64Kind.V128_WORD;
+ comparisonResult1 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind()));
+ comparisonResult2 = findTwoConsecutive ? tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())) : Value.ILLEGAL;
+ vectorKind = supportsAVX2(tool) && (maxVectorSize < 0 || maxVectorSize >= 32) ? byteMode(valueKind) ? AMD64Kind.V256_BYTE : AMD64Kind.V256_WORD
+ : byteMode(valueKind) ? AMD64Kind.V128_BYTE : AMD64Kind.V128_WORD;
vectorCompareVal1 = tool.newVariable(LIRKind.value(vectorKind));
vectorCompareVal2 = nValues > 1 ? tool.newVariable(LIRKind.value(vectorKind)) : Value.ILLEGAL;
vectorCompareVal3 = nValues > 2 ? tool.newVariable(LIRKind.value(vectorKind)) : Value.ILLEGAL;
@@ -126,7 +137,7 @@
}
private JavaKind getComparisonKind() {
- return findTwoConsecutive ? (byteMode(kind) ? JavaKind.Char : JavaKind.Int) : kind;
+ return findTwoConsecutive ? (byteMode(valueKind) ? JavaKind.Char : JavaKind.Int) : valueKind;
}
private AVXKind.AVXSize getVectorSize() {
@@ -135,15 +146,16 @@
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
+ int nVectors = nValues == 1 ? 4 : nValues == 2 ? 2 : 1;
Register arrayPtr = asRegister(arrayPtrValue);
Register arrayLength = asRegister(arrayLengthValue);
- Register result = asRegister(resultValue);
- Register slotsRemaining = asRegister(arraySlotsRemaining);
- Register[] searchValue = {
- nValues > 0 ? asRegister(searchValue1) : null,
- nValues > 1 ? asRegister(searchValue2) : null,
- nValues > 2 ? asRegister(searchValue3) : null,
- nValues > 3 ? asRegister(searchValue4) : null,
+ Register fromIndex = asRegister(fromIndexValue);
+ Register index = asRegister(resultValue);
+ Value[] searchValue = {
+ nValues > 0 ? searchValue1 : null,
+ nValues > 1 ? searchValue2 : null,
+ nValues > 2 ? searchValue3 : null,
+ nValues > 3 ? searchValue4 : null,
};
Register[] vecCmp = {
nValues > 0 ? asRegister(vectorCompareVal1) : null,
@@ -159,60 +171,9 @@
};
Register[] cmpResult = {
asRegister(comparisonResult1),
- asRegister(comparisonResult2),
- asRegister(comparisonResult3),
- asRegister(comparisonResult4),
+ findTwoConsecutive ? asRegister(comparisonResult2) : null,
};
- Label retFound = new Label();
- Label retNotFound = new Label();
- Label end = new Label();
-
- // load array length
- // important: this must be the first register manipulation, since arrayLengthValue is
- // annotated with @Use
- asm.movl(slotsRemaining, arrayLength);
- // load array pointer
- asm.movq(result, arrayPtr);
- // move search values to vectors
- for (int i = 0; i < nValues; i++) {
- if (asm.supports(CPUFeature.AVX)) {
- VexMoveOp.VMOVD.emit(asm, AVXKind.AVXSize.DWORD, vecCmp[i], searchValue[i]);
- } else {
- asm.movdl(vecCmp[i], searchValue[i]);
- }
- }
- // fill comparison vector with copies of the search value
- for (int i = 0; i < nValues; i++) {
- emitBroadcast(asm, getComparisonKind(), vecCmp[i], vecArray[0], getVectorSize());
- }
-
- emitArrayIndexOfChars(crb, asm, result, slotsRemaining, searchValue, vecCmp, vecArray, cmpResult, retFound, retNotFound);
-
- // return -1 (no match)
- asm.bind(retNotFound);
- asm.movq(result, -1);
- asm.jmpb(end);
-
- asm.bind(retFound);
- // convert array pointer to offset
- asm.subq(result, arrayPtr);
- if (charMode(kind)) {
- asm.shrq(result, 1);
- }
- asm.bind(end);
- }
-
- private void emitArrayIndexOfChars(CompilationResultBuilder crb, AMD64MacroAssembler asm,
- Register arrayPtr,
- Register slotsRemaining,
- Register[] searchValue,
- Register[] vecCmp,
- Register[] vecArray,
- Register[] cmpResult,
- Label retFound,
- Label retNotFound) {
- int nVectors = nValues == 1 ? 4 : nValues == 2 ? 2 : 1;
- AVXKind.AVXSize vectorSize = getVectorSize();
+ Label ret = new Label();
Label bulkVectorLoop = new Label();
Label singleVectorLoop = new Label();
@@ -222,225 +183,276 @@
new Label(),
new Label(),
};
- Label lessThanVectorSizeRemaining = new Label();
- Label lessThanVectorSizeRemainingLoop = new Label();
- Label bulkVectorLoopExit = nVectors == 1 ? lessThanVectorSizeRemaining : singleVectorLoop;
- int bytesPerVector = vectorSize.getBytes();
- int arraySlotsPerVector = vectorSize.getBytes() / kind.getByteCount();
- int singleVectorLoopCondition = arraySlotsPerVector;
- int bulkSize = arraySlotsPerVector * nVectors;
- int bulkSizeBytes = bytesPerVector * nVectors;
- int bulkLoopCondition = bulkSize;
- int[] vectorOffsets;
- JavaKind vectorCompareKind = kind;
+ Label runVectorized = new Label();
+ Label elementWiseLoop = new Label();
+ Label elementWiseFound = new Label();
+ Label elementWiseNotFound = new Label();
+ Label skipBulkVectorLoop = new Label();
+ int vectorSize = getVectorSize().getBytes() / valueKind.getByteCount();
+ int bulkSize = vectorSize * nVectors;
+ JavaKind vectorCompareKind = valueKind;
if (findTwoConsecutive) {
- singleVectorLoopCondition++;
- bulkLoopCondition++;
bulkSize /= 2;
- bulkSizeBytes /= 2;
- vectorOffsets = new int[]{0, kind.getByteCount(), bytesPerVector, bytesPerVector + kind.getByteCount()};
- vectorCompareKind = byteMode(kind) ? JavaKind.Char : JavaKind.Int;
+ vectorCompareKind = byteMode(valueKind) ? JavaKind.Char : JavaKind.Int;
+ }
+ // index = fromIndex + vectorSize (+1 if findTwoConsecutive)
+ // important: this must be the first register manipulation, since fromIndex is
+ // annotated with @Use
+ asm.leaq(index, new AMD64Address(fromIndex, vectorSize + (findTwoConsecutive ? 1 : 0)));
+
+ // check if vector vector load is in bounds
+ asm.cmpq(index, arrayLength);
+ asm.jccb(AMD64Assembler.ConditionFlag.LessEqual, runVectorized);
+
+ // search range is smaller than vector size, do element-wise comparison
+
+ // index = fromIndex (+ 1 if findTwoConsecutive)
+ asm.subq(index, vectorSize);
+ // check if enough array slots remain
+ asm.cmpq(index, arrayLength);
+ asm.jccb(AMD64Assembler.ConditionFlag.GreaterEqual, elementWiseNotFound);
+ // compare one-by-one
+ asm.bind(elementWiseLoop);
+ // check for match
+ OperandSize cmpSize = getOpSize(getComparisonKind());
+ // address = findTwoConsecutive ? array[index - 1] : array[index]
+ AMD64Address arrayAddr = new AMD64Address(arrayPtr, index, arrayIndexScale, arrayBaseOffset - (findTwoConsecutive ? valueKind.getByteCount() : 0));
+ boolean valuesOnStack = searchValuesOnStack(searchValue);
+ if (valuesOnStack) {
+ (cmpSize == OperandSize.BYTE ? AMD64RMOp.MOVB : AMD64RMOp.MOV).emit(asm, cmpSize, cmpResult[0], arrayAddr);
+ for (int i = 0; i < nValues; i++) {
+ if (isConstant(searchValue[i])) {
+ int imm = asConstant(searchValue[i]).asInt();
+ AMD64Assembler.AMD64BinaryArithmetic.CMP.getMIOpcode(cmpSize, NumUtil.isByte(imm)).emit(asm, cmpSize, cmpResult[0], imm);
+ } else if (isStackSlot(searchValue[i])) {
+ AMD64Assembler.AMD64BinaryArithmetic.CMP.getRMOpcode(cmpSize).emit(asm, cmpSize, cmpResult[0], (AMD64Address) crb.asAddress(searchValue[i]));
+ } else {
+ AMD64Assembler.AMD64BinaryArithmetic.CMP.getRMOpcode(cmpSize).emit(asm, cmpSize, cmpResult[0], asRegister(searchValue[i]));
+ }
+ asm.jccb(AMD64Assembler.ConditionFlag.Equal, elementWiseFound);
+ }
} else {
- vectorOffsets = new int[]{0, bytesPerVector, bytesPerVector * 2, bytesPerVector * 3};
+ for (int i = 0; i < nValues; i++) {
+ if (isConstant(searchValue[i])) {
+ int imm = asConstant(searchValue[i]).asInt();
+ AMD64Assembler.AMD64BinaryArithmetic.CMP.getMIOpcode(cmpSize, NumUtil.isByte(imm)).emit(asm, cmpSize, arrayAddr, imm);
+ } else {
+ AMD64Assembler.AMD64BinaryArithmetic.CMP.getRMOpcode(cmpSize).emit(asm, cmpSize, asRegister(searchValue[i]), arrayAddr);
+ }
+ asm.jccb(AMD64Assembler.ConditionFlag.Equal, elementWiseFound);
+ }
+ }
+ // adjust index
+ asm.incrementq(index, 1);
+ // continue loop
+ asm.cmpq(index, arrayLength);
+ asm.jccb(AMD64Assembler.ConditionFlag.Less, elementWiseLoop);
+
+ asm.bind(elementWiseNotFound);
+ asm.xorq(index, index);
+
+ if (findTwoConsecutive) {
+ asm.bind(elementWiseFound);
+ asm.decrementq(index, 1);
+ } else {
+ asm.decrementq(index, 1);
+ asm.bind(elementWiseFound);
+ }
+ asm.jmp(ret);
+
+ // vectorized implementation
+ asm.bind(runVectorized);
+
+ // move search values to vectors
+ for (int i = 0; i < nValues; i++) {
+ // fill comparison vector with copies of the search value
+ broadcastSearchValue(crb, asm, vecCmp[i], searchValue[i], cmpResult[0], vecArray[0]);
}
- // load copy of low part of array pointer
- Register tmpArrayPtrLow = cmpResult[0];
- asm.movl(tmpArrayPtrLow, arrayPtr);
-
- // check if bulk vector load is in bounds
- asm.cmpl(slotsRemaining, bulkLoopCondition);
- asm.jcc(AMD64Assembler.ConditionFlag.Below, bulkVectorLoopExit);
-
- // check if array pointer is aligned to bulkSize
- asm.andl(tmpArrayPtrLow, bulkSizeBytes - 1);
- asm.jcc(AMD64Assembler.ConditionFlag.Zero, bulkVectorLoop);
+ // do one unaligned vector comparison pass and adjust alignment afterwards
+ emitVectorCompare(asm, vectorCompareKind, findTwoConsecutive ? 2 : 1, arrayPtr, index, vecCmp, vecArray, cmpResult, vectorFound, false, false);
- // do one unaligned bulk comparison pass and adjust alignment afterwards
- emitVectorCompare(asm, vectorCompareKind, vectorSize, nValues, nVectors, vectorOffsets, arrayPtr, vecCmp, vecArray, cmpResult, vectorFound, false);
- // load copy of low part of array pointer
- asm.movl(tmpArrayPtrLow, arrayPtr);
- // adjust array pointer
- asm.addq(arrayPtr, bulkSizeBytes);
- // adjust number of array slots remaining
- asm.subl(slotsRemaining, bulkSize);
- // get offset to bulk size alignment
- asm.andl(tmpArrayPtrLow, bulkSizeBytes - 1);
- emitBytesToArraySlots(asm, kind, tmpArrayPtrLow);
- // adjust array pointer to bulk size alignment
- asm.andq(arrayPtr, ~(bulkSizeBytes - 1));
- // adjust number of array slots remaining
- asm.addl(slotsRemaining, tmpArrayPtrLow);
+ // adjust index to vector size alignment
+ asm.leaq(cmpResult[0], new AMD64Address(arrayPtr, arrayBaseOffset));
+ if (charMode(valueKind)) {
+ asm.shrq(cmpResult[0], 1);
+ }
+ asm.addq(index, cmpResult[0]);
+ // adjust to next lower multiple of vector size
+ asm.andq(index, ~(vectorSize - 1));
+ asm.subq(index, cmpResult[0]);
+ // add bulk size
+ asm.addq(index, bulkSize);
+
// check if there are enough array slots remaining for the bulk loop
- asm.cmpl(slotsRemaining, bulkLoopCondition);
- asm.jcc(AMD64Assembler.ConditionFlag.Below, bulkVectorLoopExit);
+ asm.cmpq(index, arrayLength);
+ asm.jccb(AMD64Assembler.ConditionFlag.Greater, skipBulkVectorLoop);
emitAlign(crb, asm);
asm.bind(bulkVectorLoop);
// memory-aligned bulk comparison
- emitVectorCompare(asm, vectorCompareKind, vectorSize, nValues, nVectors, vectorOffsets, arrayPtr, vecCmp, vecArray, cmpResult, vectorFound, !findTwoConsecutive);
- // adjust number of array slots remaining
- asm.subl(slotsRemaining, bulkSize);
- // adjust array pointer
- asm.addq(arrayPtr, bulkSizeBytes);
+ emitVectorCompare(asm, vectorCompareKind, nVectors, arrayPtr, index, vecCmp, vecArray, cmpResult, vectorFound, false, !findTwoConsecutive);
+ // adjust index
+ asm.addq(index, bulkSize);
// check if there are enough array slots remaining for the bulk loop
- asm.cmpl(slotsRemaining, bulkLoopCondition);
- asm.jcc(AMD64Assembler.ConditionFlag.Below, bulkVectorLoopExit);
- // continue loop
- asm.jmp(bulkVectorLoop);
+ asm.cmpq(index, arrayLength);
+ asm.jccb(AMD64Assembler.ConditionFlag.LessEqual, bulkVectorLoop);
- if (nVectors > 1) {
+ asm.bind(skipBulkVectorLoop);
+ if ((findTwoConsecutive && nVectors == 2) || nVectors == 1) {
+ // do last load from end of array
+ asm.movq(index, arrayLength);
+ // compare
+ emitVectorCompare(asm, vectorCompareKind, findTwoConsecutive ? 2 : 1, arrayPtr, index, vecCmp, vecArray, cmpResult, vectorFound, true, false);
+ } else {
+ // remove bulk offset
+ asm.subq(index, bulkSize);
emitAlign(crb, asm);
// same loop as bulkVectorLoop, with only one vector
asm.bind(singleVectorLoop);
- // check if single vector load is in bounds
- asm.cmpl(slotsRemaining, singleVectorLoopCondition);
- asm.jcc(AMD64Assembler.ConditionFlag.Below, lessThanVectorSizeRemaining);
+ // add vector size
+ asm.addq(index, vectorSize);
+ // check if vector load is in bounds
+ asm.cmpq(index, arrayLength);
+ // if load would be over bounds, set the load to the end of the array
+ asm.cmovq(AMD64Assembler.ConditionFlag.Greater, index, arrayLength);
// compare
- emitVectorCompare(asm, vectorCompareKind, vectorSize, nValues, findTwoConsecutive ? 2 : 1, vectorOffsets, arrayPtr, vecCmp, vecArray, cmpResult, vectorFound, false);
- // adjust number of array slots remaining
- asm.subl(slotsRemaining, arraySlotsPerVector);
- // adjust array pointer
- asm.addq(arrayPtr, bytesPerVector);
- // continue loop
- asm.jmpb(singleVectorLoop);
- }
-
- asm.bind(lessThanVectorSizeRemaining);
- // check if any array slots remain
- asm.testl(slotsRemaining, slotsRemaining);
- asm.jcc(AMD64Assembler.ConditionFlag.Zero, retNotFound);
-
- // a vector compare will read out of bounds of the input array.
- // check if the out-of-bounds read would cross a memory page boundary.
- // load copy of low part of array pointer
- asm.movl(tmpArrayPtrLow, arrayPtr);
- // check if pointer + vector size would cross the page boundary
- asm.andl(tmpArrayPtrLow, (vmPageSize - 1));
- asm.cmpl(tmpArrayPtrLow, (vmPageSize - (findTwoConsecutive ? bytesPerVector + kind.getByteCount() : bytesPerVector)));
- // if the page boundary would be crossed, do byte/character-wise comparison instead.
- asm.jccb(AMD64Assembler.ConditionFlag.Above, lessThanVectorSizeRemainingLoop);
-
- Label[] overBoundsMatch = {new Label(), new Label()};
- // otherwise, do a vector compare that reads beyond array bounds
- emitVectorCompare(asm, vectorCompareKind, vectorSize, nValues, findTwoConsecutive ? 2 : 1, vectorOffsets, arrayPtr, vecCmp, vecArray, cmpResult, overBoundsMatch, false);
- // no match
- asm.jmp(retNotFound);
- if (findTwoConsecutive) {
- Label overBoundsFinish = new Label();
- asm.bind(overBoundsMatch[1]);
- // get match offset of second result
- asm.bsfq(cmpResult[1], cmpResult[1]);
- asm.addl(cmpResult[1], kind.getByteCount());
- // replace first result with second and continue
- asm.movl(cmpResult[0], cmpResult[1]);
- asm.jmpb(overBoundsFinish);
-
- asm.bind(overBoundsMatch[0]);
- emitFindTwoCharPrefixMinResult(asm, kind, cmpResult, overBoundsFinish);
- } else {
- asm.bind(overBoundsMatch[0]);
- // find match offset
- asm.bsfq(cmpResult[0], cmpResult[0]);
+ emitVectorCompare(asm, vectorCompareKind, findTwoConsecutive ? 2 : 1, arrayPtr, index, vecCmp, vecArray, cmpResult, vectorFound, true, false);
+ // check if there are enough array slots remaining for the loop
+ asm.cmpq(index, arrayLength);
+ asm.jccb(AMD64Assembler.ConditionFlag.Less, singleVectorLoop);
}
- // adjust array pointer for match result
- asm.addq(arrayPtr, cmpResult[0]);
- if (charMode(kind)) {
- // convert byte offset to chars
- asm.shrl(cmpResult[0], 1);
- }
- // check if offset of matched value is greater than number of bytes remaining / out of array
- // bounds
+ asm.movl(index, -1);
+ asm.jmpb(ret);
+
if (findTwoConsecutive) {
- asm.decrementl(slotsRemaining);
- }
- asm.cmpl(cmpResult[0], slotsRemaining);
- // match is out of bounds, return no match
- asm.jcc(AMD64Assembler.ConditionFlag.GreaterEqual, retNotFound);
- // adjust number of array slots remaining
- if (findTwoConsecutive) {
- asm.incrementl(slotsRemaining, 1);
+ Label vectorFound2Done = new Label();
+
+ // vectorFound[0] and vectorFound[2] behave like the single-char case
+ asm.bind(vectorFound[2]);
+ // add static offset
+ asm.subq(index, getResultIndexDelta(2));
+ asm.jmpb(vectorFound2Done);
+
+ asm.bind(vectorFound[0]);
+ // add static offset
+ asm.subq(index, getResultIndexDelta(0));
+ asm.bind(vectorFound2Done);
+ // find offset
+ asm.bsfq(cmpResult[0], cmpResult[0]);
+ if (charMode(valueKind)) {
+ // convert byte offset to chars
+ asm.shrl(cmpResult[0], 1);
+ }
+ // add offset to index
+ asm.addq(index, cmpResult[0]);
+ asm.jmpb(ret);
+
+ Label minResult = new Label();
+ Label minResultDone = new Label();
+
+ // in vectorFound[1] and vectorFound[3], we have to check the results 0 and 2 as well
+ if (nVectors > 2) {
+ asm.bind(vectorFound[3]);
+ // add offset
+ asm.subq(index, getResultIndexDelta(3));
+ asm.jmpb(minResult);
+ }
+
+ asm.bind(vectorFound[1]);
+ // add offset
+ asm.subq(index, getResultIndexDelta(1));
+
+ asm.bind(minResult);
+ // find offset 0
+ asm.bsfq(cmpResult[1], cmpResult[1]);
+ // check if second result is also a match
+ asm.testq(cmpResult[0], cmpResult[0]);
+ asm.jccb(AMD64Assembler.ConditionFlag.Zero, minResultDone);
+ // find offset 1
+ asm.bsfq(cmpResult[0], cmpResult[0]);
+ asm.addq(cmpResult[0], valueKind.getByteCount());
+ // if first result is greater than second, replace it with the second result
+ asm.cmpq(cmpResult[1], cmpResult[0]);
+ asm.cmovq(AMD64Assembler.ConditionFlag.Greater, cmpResult[1], cmpResult[0]);
+ asm.bind(minResultDone);
+ if (charMode(valueKind)) {
+ // convert byte offset to chars
+ asm.shrl(cmpResult[1], 1);
+ }
+ // add offset to index
+ asm.addq(index, cmpResult[1]);
+ } else {
+ Label end = new Label();
+ for (int i = 0; i < nVectors; i++) {
+ asm.bind(vectorFound[i]);
+ // add static offset
+ asm.subq(index, getResultIndexDelta(i));
+ if (i < nVectors - 1) {
+ asm.jmpb(end);
+ }
+ }
+ asm.bind(end);
+ // find offset
+ asm.bsfq(cmpResult[0], cmpResult[0]);
+ if (charMode(valueKind)) {
+ // convert byte offset to chars
+ asm.shrl(cmpResult[0], 1);
+ }
+ // add offset to index
+ asm.addq(index, cmpResult[0]);
}
- asm.subl(slotsRemaining, cmpResult[0]);
- // match is in bounds, return offset
- asm.jmp(retFound);
+ asm.bind(ret);
+ }
- // compare remaining slots in the array one-by-one
- asm.bind(lessThanVectorSizeRemainingLoop);
- // check if enough array slots remain
- asm.cmpl(slotsRemaining, findTwoConsecutive ? 1 : 0);
- asm.jcc(AMD64Assembler.ConditionFlag.LessEqual, retNotFound);
- // load char / byte
- if (byteMode(kind)) {
- if (findTwoConsecutive) {
- asm.movzwl(cmpResult[0], new AMD64Address(arrayPtr));
- } else {
- asm.movzbl(cmpResult[0], new AMD64Address(arrayPtr));
- }
- } else {
- if (findTwoConsecutive) {
- asm.movl(cmpResult[0], new AMD64Address(arrayPtr));
- } else {
- asm.movzwl(cmpResult[0], new AMD64Address(arrayPtr));
+ private boolean searchValuesOnStack(Value[] searchValue) {
+ for (int i = 0; i < nValues; i++) {
+ if (isStackSlot(searchValue[i])) {
+ return true;
}
}
- // check for match
- for (int i = 0; i < nValues; i++) {
- emitCompareInst(asm, getComparisonKind(), cmpResult[0], searchValue[i]);
- asm.jcc(AMD64Assembler.ConditionFlag.Equal, retFound);
- }
- // adjust number of array slots remaining
- asm.decrementl(slotsRemaining);
- // adjust array pointer
- asm.addq(arrayPtr, kind.getByteCount());
- // continue loop
- asm.jmpb(lessThanVectorSizeRemainingLoop);
+ return false;
+ }
- for (int i = 1; i < nVectors; i += (findTwoConsecutive ? 2 : 1)) {
- emitVectorFoundWithOffset(asm, kind, vectorOffsets[i], arrayPtr, cmpResult[i], slotsRemaining, vectorFound[i], retFound);
- }
+ private int getResultIndexDelta(int i) {
+ return (((findTwoConsecutive ? i / 2 : i) + 1) * (getVectorSize().getBytes() / valueKind.getByteCount())) + (findTwoConsecutive ? (i & 1) : 0);
+ }
- if (findTwoConsecutive) {
- asm.bind(vectorFound[2]);
- asm.addq(arrayPtr, vectorOffsets[2]);
- // adjust number of array slots remaining
- asm.subl(slotsRemaining, charMode(kind) ? vectorOffsets[2] / 2 : vectorOffsets[2]);
- asm.movl(cmpResult[0], cmpResult[2]);
- asm.movl(cmpResult[1], cmpResult[3]);
- asm.bind(vectorFound[0]);
- emitFindTwoCharPrefixMinResult(asm, kind, cmpResult, new Label());
+ private int getVectorOffset(int i) {
+ return arrayBaseOffset - getResultIndexDelta(i) * valueKind.getByteCount();
+ }
+
+ private void broadcastSearchValue(CompilationResultBuilder crb, AMD64MacroAssembler asm, Register dst, Value srcVal, Register tmpReg, Register tmpVector) {
+ Register src = asRegOrTmpReg(crb, asm, srcVal, tmpReg);
+ if (asm.supports(CPUFeature.AVX)) {
+ VexMoveOp.VMOVD.emit(asm, AVXKind.AVXSize.DWORD, dst, src);
} else {
- asm.bind(vectorFound[0]);
- // find index of first set bit in bit mask
- asm.bsfq(cmpResult[0], cmpResult[0]);
+ asm.movdl(dst, src);
}
- // add offset to array pointer
- asm.addq(arrayPtr, cmpResult[0]);
- if (charMode(kind)) {
- // convert byte offset to chars
- asm.shrl(cmpResult[0], 1);
- }
- // adjust number of array slots remaining
- asm.subl(slotsRemaining, cmpResult[0]);
- asm.jmpb(retFound);
+ emitBroadcast(asm, getComparisonKind(), dst, tmpVector, getVectorSize());
}
- private static void emitFindTwoCharPrefixMinResult(AMD64MacroAssembler asm, JavaKind kind, Register[] cmpResult, Label done) {
- // find match offset
- asm.bsfq(cmpResult[0], cmpResult[0]);
- // check if second result is also a match
- asm.testl(cmpResult[1], cmpResult[1]);
- asm.jcc(AMD64Assembler.ConditionFlag.Zero, done);
- // get match offset of second result
- asm.bsfq(cmpResult[1], cmpResult[1]);
- asm.addl(cmpResult[1], kind.getByteCount());
- // check if first result is less than second
- asm.cmpl(cmpResult[0], cmpResult[1]);
- asm.jcc(AMD64Assembler.ConditionFlag.LessEqual, done);
- // first result is greater than second, replace it with the second result
- asm.movl(cmpResult[0], cmpResult[1]);
- asm.bind(done);
+ private static boolean isConstant(Value val) {
+ assert !(val instanceof ConstantValue) || ((ConstantValue) val).isJavaConstant();
+ return val instanceof ConstantValue;
+ }
+
+ private static JavaConstant asConstant(Value val) {
+ return ((ConstantValue) val).getJavaConstant();
+ }
+
+ private static Register asRegOrTmpReg(CompilationResultBuilder crb, AMD64MacroAssembler asm, Value val, Register tmpReg) {
+ if (isRegister(val)) {
+ return asRegister(val);
+ } else if (isStackSlot(val)) {
+ asm.movl(tmpReg, (AMD64Address) crb.asAddress(val));
+ return tmpReg;
+ } else {
+ assert isConstant(val);
+ asm.movl(tmpReg, asConstant(val).asInt());
+ return tmpReg;
+ }
}
private static void emitAlign(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
@@ -493,92 +505,64 @@
}
}
- /**
- * Convert a byte offset stored in {@code bytes} to an array index offset.
- */
- private static void emitBytesToArraySlots(AMD64MacroAssembler asm, JavaKind kind, Register bytes) {
- if (charMode(kind)) {
- asm.shrl(bytes, 1);
- } else {
- assert byteMode(kind);
- }
- }
-
- private static void emitVectorCompare(AMD64MacroAssembler asm,
+ private void emitVectorCompare(AMD64MacroAssembler asm,
JavaKind kind,
- AVXKind.AVXSize vectorSize,
- int nValues,
int nVectors,
- int[] vectorOffsets,
Register arrayPtr,
+ Register index,
Register[] vecCmp,
Register[] vecArray,
Register[] cmpResult,
Label[] vectorFound,
+ boolean shortJmp,
boolean alignedLoad) {
// load array contents into vectors
- for (int i = 0; i < nValues; i++) {
- for (int j = 0; j < nVectors; j++) {
- emitArrayLoad(asm, vectorSize, vecArray[(i * nVectors) + j], arrayPtr, vectorOffsets[j], alignedLoad);
+ for (int i = 0; i < nVectors; i++) {
+ int base = i * nValues;
+ for (int j = 0; j < nValues; j++) {
+ emitArrayLoad(asm, getVectorSize(), vecArray[base + j], arrayPtr, index, getVectorOffset(nVectors - (i + 1)), alignedLoad);
}
}
// compare all loaded bytes to the search value.
// matching bytes are set to 0xff, non-matching bytes are set to 0x00.
- for (int i = 0; i < nValues; i++) {
- for (int j = 0; j < nVectors; j++) {
- emitVectorCompareInst(asm, kind, vectorSize, vecArray[(i * nVectors) + j], vecCmp[i]);
+ if (!findTwoConsecutive) {
+ for (int i = 0; i < nVectors; i++) {
+ int base = i * nValues;
+ for (int j = 0; j < nValues; j++) {
+ emitVectorCompareInst(asm, kind, getVectorSize(), vecArray[base + j], vecCmp[j]);
+ if ((j & 1) == 1) {
+ emitPOR(asm, getVectorSize(), vecArray[base + j - 1], vecArray[base + j]);
+ }
+ }
+ if (nValues > 2) {
+ emitPOR(asm, getVectorSize(), vecArray[base], vecArray[base + 2]);
+ }
+ emitMOVMSK(asm, getVectorSize(), cmpResult[0], vecArray[base]);
+ emitJnz(asm, cmpResult[0], vectorFound[nVectors - (i + 1)], shortJmp);
}
- }
- // create 32-bit-masks from the most significant bit of every byte in the comparison
- // results.
- for (int i = 0; i < nValues * nVectors; i++) {
- emitMOVMSK(asm, vectorSize, cmpResult[i], vecArray[i]);
- }
- // join results of comparisons against multiple values
- for (int stride = 1; stride < nValues; stride *= 2) {
- for (int i = 0; i < nVectors; i++) {
- for (int j = 0; j + stride < nValues; j += stride * 2) {
- asm.orl(cmpResult[i + (j * nVectors)], cmpResult[i + ((j + stride) * nVectors)]);
- }
+ } else {
+ for (int i = 0; i < nVectors; i += 2) {
+ emitVectorCompareInst(asm, kind, getVectorSize(), vecArray[i], vecCmp[0]);
+ emitVectorCompareInst(asm, kind, getVectorSize(), vecArray[i + 1], vecCmp[0]);
+ emitMOVMSK(asm, getVectorSize(), cmpResult[1], vecArray[i]);
+ emitMOVMSK(asm, getVectorSize(), cmpResult[0], vecArray[i + 1]);
+ emitJnz(asm, cmpResult[1], vectorFound[nVectors - (i + 1)], shortJmp);
+ emitJnz(asm, cmpResult[0], vectorFound[nVectors - (i + 2)], shortJmp);
}
}
- // check if a match was found
- for (int i = 0; i < nVectors; i++) {
- asm.testl(cmpResult[i], cmpResult[i]);
- asm.jcc(AMD64Assembler.ConditionFlag.NotZero, vectorFound[i]);
- }
}
- private static void emitVectorFoundWithOffset(AMD64MacroAssembler asm,
- JavaKind kind,
- int resultOffset,
- Register result,
- Register cmpResult,
- Register slotsRemaining,
- Label entry,
- Label ret) {
- asm.bind(entry);
- if (resultOffset > 0) {
- // adjust array pointer
- asm.addq(result, resultOffset);
- // adjust number of array slots remaining
- asm.subl(slotsRemaining, charMode(kind) ? resultOffset / 2 : resultOffset);
+ private static void emitJnz(AMD64MacroAssembler asm, Register cond, Label tgt, boolean shortJmp) {
+ asm.testl(cond, cond);
+ if (shortJmp) {
+ asm.jccb(AMD64Assembler.ConditionFlag.NotZero, tgt);
+ } else {
+ asm.jcc(AMD64Assembler.ConditionFlag.NotZero, tgt);
}
- // find index of first set bit in bit mask
- asm.bsfq(cmpResult, cmpResult);
- // add offset to array pointer
- asm.addq(result, cmpResult);
- if (charMode(kind)) {
- // convert byte offset to chars
- asm.shrl(cmpResult, 1);
- }
- // adjust number of array slots remaining
- asm.subl(slotsRemaining, cmpResult);
- asm.jmpb(ret);
}
- private static void emitArrayLoad(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize, Register vecDst, Register arrayPtr, int offset, boolean alignedLoad) {
- AMD64Address src = new AMD64Address(arrayPtr, offset);
+ private void emitArrayLoad(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize, Register vecDst, Register arrayPtr, Register index, int offset, boolean alignedLoad) {
+ AMD64Address src = new AMD64Address(arrayPtr, index, arrayIndexScale, offset);
if (asm.supports(CPUFeature.AVX)) {
VexMoveOp loadOp = alignedLoad ? VexMoveOp.VMOVDQA : VexMoveOp.VMOVDQU;
loadOp.emit(asm, vectorSize, vecDst, src);
@@ -621,6 +605,15 @@
}
}
+ private static void emitPOR(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize, Register dst, Register vecSrc) {
+ if (asm.supports(CPUFeature.AVX)) {
+ VexRVMOp.VPOR.emit(asm, vectorSize, dst, dst, vecSrc);
+ } else {
+ // SSE
+ asm.por(dst, vecSrc);
+ }
+ }
+
private static void emitMOVMSK(AMD64MacroAssembler asm, AVXKind.AVXSize vectorSize, Register dst, Register vecSrc) {
if (asm.supports(CPUFeature.AVX)) {
VexRMOp.VPMOVMSKB.emit(asm, vectorSize, dst, vecSrc);
@@ -630,20 +623,17 @@
}
}
- private static void emitCompareInst(AMD64MacroAssembler asm, JavaKind kind, Register dst, Register src) {
+ private static OperandSize getOpSize(JavaKind kind) {
switch (kind) {
case Byte:
- asm.cmpb(dst, src);
- break;
+ return OperandSize.BYTE;
case Short:
case Char:
- asm.cmpw(dst, src);
- break;
+ return OperandSize.WORD;
case Int:
- asm.cmpl(dst, src);
- break;
+ return OperandSize.DWORD;
default:
- asm.cmpq(dst, src);
+ return OperandSize.QWORD;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/BailoutAndRestartBackendException.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/BailoutAndRestartBackendException.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,24 +25,12 @@
package org.graalvm.compiler.lir;
import org.graalvm.compiler.core.common.PermanentBailoutException;
-import org.graalvm.compiler.options.Option;
-import org.graalvm.compiler.options.OptionKey;
-import org.graalvm.compiler.options.OptionType;
/**
* Restarts the {@link LIR low-level} compilation with a modified configuration.
- * {@link BailoutAndRestartBackendException.Options#LIRUnlockBackendRestart LIRUnlockBackendRestart}
- * needs to be enabled. Use only for debugging purposes only.
*/
public abstract class BailoutAndRestartBackendException extends PermanentBailoutException {
- public static class Options {
- // @formatter:off
- @Option(help = "Unlock backend restart feature.", type = OptionType.Debug)
- public static final OptionKey<Boolean> LIRUnlockBackendRestart = new OptionKey<>(false);
- // @formatter:on
- }
-
private static final long serialVersionUID = 792969002851591180L;
public BailoutAndRestartBackendException(String msg) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java Fri Jun 28 14:36:42 2019 +0530
@@ -34,8 +34,8 @@
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
+import org.graalvm.compiler.lir.StandardOp.LabelHoldingOp;
import org.graalvm.compiler.lir.StandardOp.LabelOp;
-import org.graalvm.compiler.lir.StandardOp.LabelHoldingOp;
import org.graalvm.compiler.lir.gen.LIRGenerator;
import org.graalvm.compiler.options.OptionValues;
@@ -72,7 +72,11 @@
/**
* Creates a new LIR instance for the specified compilation.
*/
- public LIR(AbstractControlFlowGraph<?> cfg, AbstractBlockBase<?>[] linearScanOrder, AbstractBlockBase<?>[] codeEmittingOrder, OptionValues options, DebugContext debug) {
+ public LIR(AbstractControlFlowGraph<?> cfg,
+ AbstractBlockBase<?>[] linearScanOrder,
+ AbstractBlockBase<?>[] codeEmittingOrder,
+ OptionValues options,
+ DebugContext debug) {
this.cfg = cfg;
this.codeEmittingOrder = codeEmittingOrder;
this.linearScanOrder = linearScanOrder;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarkerPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarkerPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -37,14 +37,15 @@
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.phases.AllocationPhase;
+import jdk.vm.ci.code.ReferenceMap;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.RegisterAttributes;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.Value;
/**
- * Mark all live references for a frame state. The frame state use this information to build the OOP
- * maps.
+ * Mark all live references for a frame state. The frame state uses this information to build the
+ * {@link ReferenceMap}s.
*/
public final class LocationMarkerPhase extends AllocationPhase {
@@ -93,7 +94,6 @@
}
ReferenceMapBuilder refMap = frameMap.newReferenceMapBuilder();
- frameMap.addLiveValues(refMap);
values.addLiveValues(refMap);
info.debugInfo().setReferenceMap(refMap.finish(info));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMap.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMap.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,13 +24,9 @@
package org.graalvm.compiler.lir.framemap;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-
+import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.PermanentBailoutException;
-import org.graalvm.compiler.core.common.LIRKind;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.CallingConvention;
@@ -38,14 +34,13 @@
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.Value;
import jdk.vm.ci.meta.ValueKind;
/**
* This class is used to build the stack frame layout for a compiled method. A {@link StackSlot} is
* used to index slots of the frame relative to the stack pointer. The frame size is only fixed
* after register allocation when all spill slots have been allocated. Both the outgoing argument
- * area and the spill are can grow until then. Therefore, outgoing arguments are indexed from the
+ * area and the spill area can grow until then. Therefore, outgoing arguments are indexed from the
* stack pointer, while spill slots are indexed from the beginning of the frame (and the total frame
* size has to be added to get the actual offset from the stack pointer).
*/
@@ -91,11 +86,6 @@
protected boolean hasOutgoingStackArguments;
/**
- * The list of stack slots allocated in this frame that are present in every reference map.
- */
- private final List<StackSlot> objectStackSlots;
-
- /**
* Records whether an offset to an incoming stack argument was ever returned by
* {@link #offsetForStackSlot(StackSlot)}.
*/
@@ -110,7 +100,6 @@
this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig;
this.frameSize = -1;
this.outgoingSize = codeCache.getMinimumOutgoingSize();
- this.objectStackSlots = new ArrayList<>();
this.referenceMapFactory = referenceMapFactory;
}
@@ -122,12 +111,6 @@
return target;
}
- public void addLiveValues(ReferenceMapBuilder refMap) {
- for (Value value : objectStackSlots) {
- refMap.addLiveValue(value);
- }
- }
-
protected int returnAddressSize() {
return getTarget().arch.getReturnAddressSize();
}
@@ -235,19 +218,6 @@
}
/**
- * Reserves a new spill slot in the frame of the method being compiled. The returned slot is
- * aligned on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte
- * boundary.
- *
- * @param kind The kind of the spill slot to be reserved.
- * @param additionalOffset
- * @return A spill slot denoting the reserved memory area.
- */
- protected StackSlot allocateNewSpillSlot(ValueKind<?> kind, int additionalOffset) {
- return StackSlot.get(kind, -spillSize + additionalOffset, true);
- }
-
- /**
* Returns the spill slot size for the given {@link ValueKind}. The default value is the size in
* bytes for the target architecture.
*
@@ -270,7 +240,11 @@
assert frameSize == -1 : "frame size must not yet be fixed";
int size = spillSlotSize(kind);
spillSize = NumUtil.roundUp(spillSize + size, size);
- return allocateNewSpillSlot(kind, 0);
+ return newStackSlot(kind);
+ }
+
+ private StackSlot newStackSlot(ValueKind<?> kind) {
+ return StackSlot.get(kind, -spillSize, true);
}
/**
@@ -288,46 +262,15 @@
* requested number of slots is 0, this method returns {@code null}.
*
* @param slots the number of slots to reserve
- * @param objects specifies the indexes of the object pointer slots. The caller is responsible
- * for guaranteeing that each such object pointer slot is initialized before any
- * instruction that uses a reference map. Without this guarantee, the garbage
- * collector could see garbage object values.
* @return the first reserved stack slot (i.e., at the lowest address)
*/
- public StackSlot allocateStackSlots(int slots, BitSet objects) {
+ public StackSlot allocateStackSlots(int slots) {
assert frameSize == -1 : "frame size must not yet be fixed";
if (slots == 0) {
return null;
}
- spillSize += spillSlotRangeSize(slots);
-
- if (!objects.isEmpty()) {
- assert objects.length() <= slots;
- StackSlot result = null;
- for (int slotIndex = 0; slotIndex < slots; slotIndex++) {
- StackSlot objectSlot = null;
- if (objects.get(slotIndex)) {
- objectSlot = allocateNewSpillSlot(LIRKind.reference(getTarget().arch.getWordKind()), slotIndex * getTarget().wordSize);
- addObjectStackSlot(objectSlot);
- }
- if (slotIndex == 0) {
- if (objectSlot != null) {
- result = objectSlot;
- } else {
- result = allocateNewSpillSlot(LIRKind.value(getTarget().arch.getWordKind()), 0);
- }
- }
- }
- assert result != null;
- return result;
-
- } else {
- return allocateNewSpillSlot(LIRKind.value(getTarget().arch.getWordKind()), 0);
- }
- }
-
- protected void addObjectStackSlot(StackSlot objectSlot) {
- objectStackSlots.add(objectSlot);
+ spillSize = NumUtil.roundUp(spillSize + spillSlotRangeSize(slots), getTarget().wordSize);
+ return newStackSlot(LIRKind.value(getTarget().arch.getWordKind()));
}
public ReferenceMapBuilder newReferenceMapBuilder() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilder.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilder.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,9 +24,6 @@
package org.graalvm.compiler.lir.framemap;
-import java.util.BitSet;
-import java.util.List;
-
import org.graalvm.compiler.lir.VirtualStackSlot;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
@@ -56,15 +53,9 @@
* requested number of slots is 0, this method returns {@code null}.
*
* @param slots the number of slots to reserve
- * @param objects specifies the indexes of the object pointer slots. The caller is responsible
- * for guaranteeing that each such object pointer slot is initialized before any
- * instruction that uses a reference map. Without this guarantee, the garbage
- * collector could see garbage object values.
- * @param outObjectStackSlots if non-null, the object pointer slots allocated are added to this
- * list
* @return the first reserved stack slot (i.e., at the lowest address)
*/
- public abstract VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots);
+ public abstract VirtualStackSlot allocateStackSlots(int slots);
public abstract RegisterConfig getRegisterConfig();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,14 +27,12 @@
import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
import java.util.ArrayList;
-import java.util.BitSet;
import java.util.EnumSet;
import java.util.List;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.InstructionValueConsumer;
import org.graalvm.compiler.lir.LIR;
import org.graalvm.compiler.lir.LIRInstruction;
@@ -46,7 +44,6 @@
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.RegisterConfig;
-import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
import jdk.vm.ci.meta.ValueKind;
@@ -80,14 +77,11 @@
}
@Override
- public VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots) {
+ public VirtualStackSlot allocateStackSlots(int slots) {
if (slots == 0) {
return null;
}
- if (outObjectStackSlots != null) {
- throw GraalError.unimplemented();
- }
- VirtualStackSlotRange slot = new VirtualStackSlotRange(numStackSlots++, slots, objects, LIRKind.fromJavaKind(frameMap.getTarget().arch, JavaKind.Object));
+ VirtualStackSlotRange slot = new VirtualStackSlotRange(numStackSlots++, slots, LIRKind.value(frameMap.getTarget().arch.getWordKind()));
stackSlots.add(slot);
return slot;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/VirtualStackSlotRange.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/VirtualStackSlotRange.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,8 +24,6 @@
package org.graalvm.compiler.lir.framemap;
-import java.util.BitSet;
-
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.lir.VirtualStackSlot;
@@ -37,21 +35,14 @@
*/
public class VirtualStackSlotRange extends VirtualStackSlot {
- private final BitSet objects;
private final int slots;
- public VirtualStackSlotRange(int id, int slots, BitSet objects, LIRKind kind) {
+ public VirtualStackSlotRange(int id, int slots, LIRKind kind) {
super(id, kind);
this.slots = slots;
- this.objects = (BitSet) objects.clone();
}
public int getSlots() {
return slots;
}
-
- public BitSet getObjects() {
- return (BitSet) objects.clone();
- }
-
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,9 +24,6 @@
package org.graalvm.compiler.lir.gen;
-import java.util.BitSet;
-import java.util.List;
-
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.calc.Condition;
@@ -274,7 +271,7 @@
}
@SuppressWarnings("unused")
- default Variable emitArrayIndexOf(JavaKind kind, boolean findTwoConsecutive, Value sourcePointer, Value sourceCount, Value... searchValues) {
+ default Variable emitArrayIndexOf(JavaKind arrayKind, JavaKind valueKind, boolean findTwoConsecutive, Value sourcePointer, Value sourceCount, Value fromIndex, Value... searchValues) {
throw GraalError.unimplemented("String.indexOf substitution is not implemented on this architecture");
}
@@ -324,8 +321,8 @@
*/
void emitSpeculationFence();
- default VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots) {
- return getResult().getFrameMapBuilder().allocateStackSlots(slots, objects, outObjectStackSlots);
+ default VirtualStackSlot allocateStackSlots(int slots) {
+ return getResult().getFrameMapBuilder().allocateStackSlots(slots);
}
default Value emitReadCallerStackPointer(Stamp wordStamp) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,11 +33,12 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
-import java.util.EnumMap;
import java.util.EnumSet;
import java.util.PriorityQueue;
+import java.util.function.Predicate;
import jdk.internal.vm.compiler.collections.EconomicSet;
+import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
@@ -49,6 +50,7 @@
import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
import org.graalvm.compiler.lir.ValueProcedure;
import org.graalvm.compiler.lir.VirtualStackSlot;
+import org.graalvm.compiler.lir.framemap.FrameMap;
import org.graalvm.compiler.lir.framemap.FrameMapBuilderTool;
import org.graalvm.compiler.lir.framemap.SimpleVirtualStackSlot;
import org.graalvm.compiler.lir.framemap.VirtualStackSlotRange;
@@ -58,6 +60,7 @@
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionType;
+import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.Value;
@@ -156,7 +159,15 @@
}
// step 4: allocate stack slots
try (DebugCloseable t = AllocateSlotsTimer.start(debug)) {
- allocateStackSlots();
+ /*
+ * Allocate primitive spill slots before reference spill slots. This ensures a
+ * ReferenceMap will be as compact as possible and only exceed the encoding limit of
+ * a stack offset if there are really too many objects live on the stack at an
+ * instruction with a ReferenceMap (as opposed to the method simply having a very
+ * large frame).
+ */
+ allocateStackSlots(IS_PRIMITIVE_INTERVAL);
+ allocateStackSlots(IS_REFERENCE_INTERVAL);
}
if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) {
dumpIntervals("After stack slot allocation");
@@ -226,29 +237,44 @@
// ====================
@SuppressWarnings("try")
- private void allocateStackSlots() {
- // create unhandled lists
+ private void allocateStackSlots(Predicate<StackInterval> predicate) {
for (StackInterval interval : stackSlotMap) {
- if (interval != null) {
+ if (interval != null && (predicate == null || predicate.test(interval))) {
unhandled.add(interval);
}
}
-
for (StackInterval current = activateNext(); current != null; current = activateNext()) {
try (Indent indent = debug.logAndIndent("allocate %s", current)) {
allocateSlot(current);
}
}
+ // Cannot re-use free slots between rounds of slot allocation
+ freeSlots = null;
+ active.clear();
}
+ private static final Predicate<StackInterval> IS_REFERENCE_INTERVAL = new Predicate<StackInterval>() {
+ @Override
+ public boolean test(StackInterval interval) {
+ return !((LIRKind) interval.kind()).isValue();
+ }
+ };
+
+ private static final Predicate<StackInterval> IS_PRIMITIVE_INTERVAL = new Predicate<StackInterval>() {
+ @Override
+ public boolean test(StackInterval interval) {
+ return ((LIRKind) interval.kind()).isValue();
+ }
+ };
+
private void allocateSlot(StackInterval current) {
VirtualStackSlot virtualSlot = current.getOperand();
final StackSlot location;
if (virtualSlot instanceof VirtualStackSlotRange) {
// No reuse of ranges (yet).
VirtualStackSlotRange slotRange = (VirtualStackSlotRange) virtualSlot;
- location = frameMapBuilder.getFrameMap().allocateStackSlots(slotRange.getSlots(), slotRange.getObjects());
+ location = frameMapBuilder.getFrameMap().allocateStackSlots(slotRange.getSlots());
StackSlotAllocatorUtil.virtualFramesize.add(debug, frameMapBuilder.getFrameMap().spillSlotRangeSize(slotRange.getSlots()));
StackSlotAllocatorUtil.allocatedSlots.increment(debug);
} else {
@@ -274,59 +300,44 @@
current.setLocation(location);
}
- private enum SlotSize {
- Size1,
- Size2,
- Size4,
- Size8,
- Illegal;
- }
-
- private SlotSize forKind(ValueKind<?> kind) {
- switch (frameMapBuilder.getFrameMap().spillSlotSize(kind)) {
- case 1:
- return SlotSize.Size1;
- case 2:
- return SlotSize.Size2;
- case 4:
- return SlotSize.Size4;
- case 8:
- return SlotSize.Size8;
- default:
- return SlotSize.Illegal;
- }
- }
-
- private EnumMap<SlotSize, Deque<StackSlot>> freeSlots;
+ /**
+ * Map from log2 of {@link FrameMap#spillSlotSize(ValueKind) a spill slot size} to a list of
+ * free stack slots.
+ */
+ private ArrayList<Deque<StackSlot>> freeSlots;
/**
- * @return The list of free stack slots for {@code size} or {@code null} if there is none.
+ * @return The list of free stack slots for {@code index} or {@code null} if there is none.
*/
- private Deque<StackSlot> getOrNullFreeSlots(SlotSize size) {
+ private Deque<StackSlot> getNullOrFreeSlots(int index) {
if (freeSlots == null) {
return null;
}
- return freeSlots.get(size);
+ if (index < freeSlots.size()) {
+ return freeSlots.get(index);
+ }
+ return null;
}
/**
- * @return the list of free stack slots for {@code size}. If there is none a list is
+ * @return the list of free stack slots for {@code index}. If there is none a list is
* created.
*/
- private Deque<StackSlot> getOrInitFreeSlots(SlotSize size) {
- assert size != SlotSize.Illegal;
- Deque<StackSlot> freeList;
- if (freeSlots != null) {
- freeList = freeSlots.get(size);
- } else {
- freeSlots = new EnumMap<>(SlotSize.class);
- freeList = null;
+ private Deque<StackSlot> getOrInitFreeSlots(int index) {
+ Deque<StackSlot> freeList = null;
+ if (freeSlots == null) {
+ freeSlots = new ArrayList<>(6);
+ } else if (index < freeSlots.size()) {
+ freeList = freeSlots.get(index);
}
if (freeList == null) {
+ int requiredSize = index + 1;
+ for (int i = freeSlots.size(); i < requiredSize; i++) {
+ freeSlots.add(null);
+ }
freeList = new ArrayDeque<>();
- freeSlots.put(size, freeList);
+ freeSlots.set(index, freeList);
}
- assert freeList != null;
return freeList;
}
@@ -335,11 +346,8 @@
*/
private StackSlot findFreeSlot(SimpleVirtualStackSlot slot) {
assert slot != null;
- SlotSize size = forKind(slot.getValueKind());
- if (size == SlotSize.Illegal) {
- return null;
- }
- Deque<StackSlot> freeList = getOrNullFreeSlots(size);
+ int size = log2SpillSlotSize(slot.getValueKind());
+ Deque<StackSlot> freeList = getNullOrFreeSlots(size);
if (freeList == null) {
return null;
}
@@ -350,13 +358,16 @@
* Adds a stack slot to the list of free slots.
*/
private void freeSlot(StackSlot slot) {
- SlotSize size = forKind(slot.getValueKind());
- if (size == SlotSize.Illegal) {
- return;
- }
+ int size = log2SpillSlotSize(slot.getValueKind());
getOrInitFreeSlots(size).addLast(slot);
}
+ private int log2SpillSlotSize(ValueKind<?> kind) {
+ int size = frameMapBuilder.getFrameMap().spillSlotSize(kind);
+ assert CodeUtil.isPowerOf2(size);
+ return CodeUtil.log2(size);
+ }
+
/**
* Gets the next unhandled interval and finishes handled intervals.
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java Fri Jun 28 14:36:42 2019 +0530
@@ -113,6 +113,6 @@
}
protected StackSlot mapVirtualStackSlotRange(FrameMapBuilderTool builder, VirtualStackSlotRange virtualStackSlot) {
- return builder.getFrameMap().allocateStackSlots(virtualStackSlot.getSlots(), virtualStackSlot.getObjects());
+ return builder.getFrameMap().allocateStackSlots(virtualStackSlot.getSlots());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ContextlessLoopPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ContextlessLoopPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,7 +26,7 @@
import org.graalvm.compiler.loop.LoopPolicies;
import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
public abstract class ContextlessLoopPhase<P extends LoopPolicies> extends LoopPhase<P> {
@@ -45,7 +45,7 @@
protected abstract void run(StructuredGraph graph);
@Override
- protected final void run(StructuredGraph graph, PhaseContext context) {
+ protected final void run(StructuredGraph graph, CoreProviders context) {
run(graph);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -59,12 +59,12 @@
import org.graalvm.compiler.nodes.ValuePhiNode;
import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.cfg.Block;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.LazyValue;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.DeoptimizationAction;
@@ -81,10 +81,10 @@
* {@link DeoptimizeNode} as close to the {@link ControlSplitNode} as possible.
*
*/
-public class ConvertDeoptimizeToGuardPhase extends BasePhase<PhaseContext> {
+public class ConvertDeoptimizeToGuardPhase extends BasePhase<CoreProviders> {
@Override
@SuppressWarnings("try")
- protected void run(final StructuredGraph graph, PhaseContext context) {
+ protected void run(final StructuredGraph graph, CoreProviders context) {
assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies";
assert !graph.getGuardsStage().areFrameStatesAtDeopts() : graph.getGuardsStage();
LazyValue<LoopsData> lazyLoops = new LazyValue<>(() -> new LoopsData(graph));
@@ -110,7 +110,7 @@
new DeadCodeEliminationPhase(Optional).apply(graph);
}
- private static void trySplitFixedGuard(FixedGuardNode fixedGuard, PhaseContext context, LazyValue<LoopsData> lazyLoops) {
+ private static void trySplitFixedGuard(FixedGuardNode fixedGuard, CoreProviders context, LazyValue<LoopsData> lazyLoops) {
LogicNode condition = fixedGuard.condition();
if (condition instanceof CompareNode) {
CompareNode compare = (CompareNode) condition;
@@ -126,7 +126,7 @@
}
}
- private static void processFixedGuardAndPhis(FixedGuardNode fixedGuard, PhaseContext context, CompareNode compare, ValueNode x, ValuePhiNode xPhi, ValueNode y, ValuePhiNode yPhi,
+ private static void processFixedGuardAndPhis(FixedGuardNode fixedGuard, CoreProviders context, CompareNode compare, ValueNode x, ValuePhiNode xPhi, ValueNode y, ValuePhiNode yPhi,
LazyValue<LoopsData> lazyLoops) {
AbstractBeginNode pred = AbstractBeginNode.prevBegin(fixedGuard);
if (pred instanceof AbstractMergeNode) {
@@ -143,7 +143,7 @@
}
@SuppressWarnings("try")
- private static void processFixedGuardAndMerge(FixedGuardNode fixedGuard, PhaseContext context, CompareNode compare, ValueNode x, ValuePhiNode xPhi, ValueNode y, ValuePhiNode yPhi,
+ private static void processFixedGuardAndMerge(FixedGuardNode fixedGuard, CoreProviders context, CompareNode compare, ValueNode x, ValuePhiNode xPhi, ValueNode y, ValuePhiNode yPhi,
AbstractMergeNode merge, LazyValue<LoopsData> lazyLoops) {
List<EndNode> mergePredecessors = merge.cfgPredecessors().snapshot();
for (AbstractEndNode mergePredecessor : mergePredecessors) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopFullUnrollPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,14 +24,15 @@
package org.graalvm.compiler.loop.phases;
+import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.loop.LoopEx;
import org.graalvm.compiler.loop.LoopPolicies;
import org.graalvm.compiler.loop.LoopsData;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
public class LoopFullUnrollPhase extends LoopPhase<LoopPolicies> {
@@ -44,26 +45,28 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
- DebugContext debug = graph.getDebug();
- if (graph.hasLoops()) {
- boolean peeled;
- do {
- peeled = false;
- final LoopsData dataCounted = new LoopsData(graph);
- dataCounted.detectedCountedLoops();
- for (LoopEx loop : dataCounted.countedLoops()) {
- if (getPolicies().shouldFullUnroll(loop)) {
- debug.log("FullUnroll %s", loop);
- LoopTransformations.fullUnroll(loop, context, canonicalizer);
- FULLY_UNROLLED_LOOPS.increment(debug);
- debug.dump(DebugContext.DETAILED_LEVEL, graph, "FullUnroll %s", loop);
- peeled = true;
- break;
+ protected void run(StructuredGraph graph, CoreProviders context) {
+ if (GraalOptions.FullUnroll.getValue(graph.getOptions())) {
+ DebugContext debug = graph.getDebug();
+ if (graph.hasLoops()) {
+ boolean peeled;
+ do {
+ peeled = false;
+ final LoopsData dataCounted = new LoopsData(graph);
+ dataCounted.detectedCountedLoops();
+ for (LoopEx loop : dataCounted.countedLoops()) {
+ if (getPolicies().shouldFullUnroll(loop)) {
+ debug.log("FullUnroll %s", loop);
+ LoopTransformations.fullUnroll(loop, context, canonicalizer);
+ FULLY_UNROLLED_LOOPS.increment(debug);
+ debug.dump(DebugContext.DETAILED_LEVEL, graph, "FullUnroll %s", loop);
+ peeled = true;
+ break;
+ }
}
- }
- dataCounted.deleteUnusedNodes();
- } while (peeled);
+ dataCounted.deleteUnusedNodes();
+ } while (peeled);
+ }
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,9 +33,9 @@
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.extended.OpaqueNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
public class LoopPartialUnrollPhase extends LoopPhase<LoopPolicies> {
@@ -48,7 +48,7 @@
@Override
@SuppressWarnings("try")
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
if (graph.hasLoops()) {
EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener();
boolean changed = true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPeelingPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,7 +29,7 @@
import org.graalvm.compiler.loop.LoopPolicies;
import org.graalvm.compiler.loop.LoopsData;
import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
public class LoopPeelingPhase extends LoopPhase<LoopPolicies> {
@@ -39,7 +39,7 @@
@Override
@SuppressWarnings("try")
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
DebugContext debug = graph.getDebug();
if (graph.hasLoops()) {
LoopsData data = new LoopsData(graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,10 +25,10 @@
package org.graalvm.compiler.loop.phases;
import org.graalvm.compiler.loop.LoopPolicies;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
-public abstract class LoopPhase<P extends LoopPolicies> extends BasePhase<PhaseContext> {
+public abstract class LoopPhase<P extends LoopPolicies> extends BasePhase<CoreProviders> {
private P policies;
public LoopPhase(P policies) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java Fri Jun 28 14:36:42 2019 +0530
@@ -65,8 +65,8 @@
import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
import org.graalvm.compiler.nodes.extended.OpaqueNode;
import org.graalvm.compiler.nodes.extended.SwitchNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
public abstract class LoopTransformations {
@@ -79,7 +79,7 @@
loop.loopBegin().setLoopFrequency(Math.max(0.0, loop.loopBegin().loopFrequency() - 1));
}
- public static void fullUnroll(LoopEx loop, PhaseContext context, CanonicalizerPhase canonicalizer) {
+ public static void fullUnroll(LoopEx loop, CoreProviders context, CanonicalizerPhase canonicalizer) {
// assert loop.isCounted(); //TODO (gd) strengthen : counted with known trip count
LoopBeginNode loopBegin = loop.loopBegin();
StructuredGraph graph = loopBegin.graph();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -62,14 +62,14 @@
public class LoopPartialUnrollTest extends GraalCompilerTest {
@Override
- protected boolean checkMidTierGraph(StructuredGraph graph) {
+ protected void checkMidTierGraph(StructuredGraph graph) {
NodeIterable<LoopBeginNode> loops = graph.getNodes().filter(LoopBeginNode.class);
for (LoopBeginNode loop : loops) {
if (loop.isMainLoop()) {
- return true;
+ return;
}
}
- return false;
+ fail("expected a main loop");
}
public static long sumWithEqualityLimit(int[] text) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Fri Jun 28 14:36:42 2019 +0530
@@ -387,7 +387,7 @@
if (loop.isOutsideLoop(op)) {
continue;
}
- if (op.usages().count() == 1 && op.usages().first() == baseIvNode) {
+ if (op.hasExactlyOneUsage() && op.usages().first() == baseIvNode) {
/*
* This is just the base induction variable increment with no other uses so
* don't bother reporting it.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/ConditionalEliminationBenchmark.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/graal/ConditionalEliminationBenchmark.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,7 +28,6 @@
import org.graalvm.compiler.microbenchmarks.graal.util.GraphState;
import org.graalvm.compiler.microbenchmarks.graal.util.MethodSpec;
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.openjdk.jmh.annotations.Benchmark;
public class ConditionalEliminationBenchmark extends GraalBenchmark {
@@ -109,12 +108,12 @@
@Benchmark
public void nullness(Nullness s, GraalState g) {
- new ConditionalEliminationPhase(false).apply(s.graph, new PhaseContext(g.providers));
+ new ConditionalEliminationPhase(false).apply(s.graph, g.providers);
}
@Benchmark
public void newDominatorConditionalElimination(Nullness s, GraalState g) {
- new ConditionalEliminationPhase(false).apply(s.graph, new PhaseContext(g.providers));
+ new ConditionalEliminationPhase(false).apply(s.graph, g.providers);
}
@MethodSpec(declaringClass = ConditionalEliminationBenchmark.class, name = "searchSnippet")
@@ -165,6 +164,6 @@
@Benchmark
public void search(Search s, GraalState g) {
- new ConditionalEliminationPhase(false).apply(s.graph, new PhaseContext(g.providers));
+ new ConditionalEliminationPhase(false).apply(s.graph, g.providers);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,22 +24,21 @@
package org.graalvm.compiler.nodes.test;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.nodes.IfNode;
import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.calc.SubNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
/**
* A few tests of expected simplifications by
@@ -156,7 +155,7 @@
public void test(String name, Class<? extends Node> expectedClass, int expectedCount) {
StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
new ConvertDeoptimizeToGuardPhase().apply(graph, context);
graph.clearAllStateAfter();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/LoopPhiCanonicalizerTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/LoopPhiCanonicalizerTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,18 +24,17 @@
package org.graalvm.compiler.nodes.test;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.graph.iterators.NodePredicate;
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
public class LoopPhiCanonicalizerTest extends GraalCompilerTest {
@@ -66,7 +65,7 @@
StructuredGraph graph = parseEager("loopSnippet", AllowAssumptions.YES);
NodePredicate loopPhis = node -> node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode;
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
Assert.assertEquals(5, graph.getNodes().filter(loopPhis).count());
new CanonicalizerPhase().apply(graph, context);
Assert.assertEquals(2, graph.getNodes().filter(loopPhis).count());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ShortCircuitOrNodeTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/ShortCircuitOrNodeTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -39,12 +39,12 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.FloatingReadPhase;
import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
import org.junit.Test;
@@ -377,7 +377,7 @@
for (int i = 1; i <= 64; ++i) {
String snippet = "testCascadeSnippet" + i;
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
canonicalizer.apply(graph, context);
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Fri Jun 28 14:36:42 2019 +0530
@@ -512,8 +512,8 @@
if (expectedNode instanceof EndNode) {
/* Visit the merge node, which is the one and only usage of the EndNode. */
- assert expectedNode.usages().count() == 1;
- assert actualNode.usages().count() == 1;
+ assert expectedNode.hasExactlyOneUsage();
+ assert actualNode.hasExactlyOneUsage();
verifyNodesEqual(expectedNode.usages(), actualNode.usages(), nodeMapping, workList, false);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
import org.graalvm.compiler.bytecode.Bytes;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
import org.graalvm.compiler.core.common.calc.Condition;
+import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -56,6 +57,7 @@
import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.calc.ConditionalNode;
import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
@@ -295,7 +297,8 @@
return;
}
- if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) {
+ if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode &&
+ !(((IfNode) falseSuccessor().next()).falseSuccessor() instanceof LoopExitNode)) {
AbstractBeginNode intermediateBegin = falseSuccessor();
IfNode nextIf = (IfNode) intermediateBegin.next();
double probabilityB = (1.0 - this.trueSuccessorProbability) * nextIf.trueSuccessorProbability;
@@ -465,7 +468,7 @@
return false;
}
MergeNode merge = (MergeNode) trueEnd.merge();
- if (merge.usages().count() != 1 || merge.phis().count() != 1) {
+ if (!merge.hasExactlyOneUsage() || merge.phis().count() != 1) {
return false;
}
@@ -789,6 +792,7 @@
ValueNode trueValue = trueEnd.result();
ValueNode falseValue = falseEnd.result();
ValueNode value = null;
+ boolean needsProxy = false;
if (trueValue != null) {
if (trueValue == falseValue) {
value = trueValue;
@@ -797,8 +801,20 @@
if (value == null) {
return false;
}
+ needsProxy = true;
}
}
+
+ if (trueSuccessor() instanceof LoopExitNode) {
+ LoopBeginNode loopBegin = ((LoopExitNode) trueSuccessor()).loopBegin();
+ assert loopBegin == ((LoopExitNode) falseSuccessor()).loopBegin();
+ LoopExitNode loopExitNode = graph().add(new LoopExitNode(loopBegin));
+ graph().addBeforeFixed(this, loopExitNode);
+ if (graph().hasValueProxies() && needsProxy) {
+ value = graph().addOrUnique(new ValueProxyNode(value, loopExitNode));
+ }
+ }
+
ReturnNode newReturn = graph().add(new ReturnNode(value));
replaceAtPredecessor(newReturn);
GraphUtil.killCFG(this);
@@ -834,7 +850,7 @@
* we can collapse all proxy nodes on one loop exit, the surviving one, which will
* be the true successor
*/
- if (falseSuccessor.anchored().isEmpty() && falseSuccessor.usages().isNotEmpty()) {
+ if (falseSuccessor.anchored().isEmpty() && falseSuccessor.hasUsages()) {
for (Node n : falseSuccessor.usages().snapshot()) {
assert n instanceof ProxyNode;
((ProxyNode) n).setProxyPoint((LoopExitNode) trueSuccessor);
@@ -844,7 +860,7 @@
* The true successor (surviving loop exit) can have usages, namely proxy nodes, the
* false successor however, must not have usages any more after the code above
*/
- assert trueSuccessor.anchored().isEmpty() && falseSuccessor.usages().isEmpty();
+ assert trueSuccessor.anchored().isEmpty() && falseSuccessor.hasNoUsages();
return this.graph().addOrUnique(new ValueProxyNode(replacement, (LoopExitNode) trueSuccessor));
}
}
@@ -947,16 +963,18 @@
if (constant.isJavaConstant() && conditional.trueValue().isJavaConstant() && conditional.falseValue().isJavaConstant() && condition() instanceof CompareNode &&
conditional.condition() instanceof CompareNode) {
- Condition cond1 = ((CompareNode) condition()).condition().asCondition();
+ CompareNode condition1 = (CompareNode) condition();
+ Condition cond1 = condition1.condition().asCondition();
if (negateCondition) {
cond1 = cond1.negate();
}
// cond1 is EQ, NE, LT, or GE
- Condition cond2 = ((CompareNode) conditional.condition()).condition().asCondition();
- ValueNode x = ((CompareNode) condition()).getX();
- ValueNode y = ((CompareNode) condition()).getY();
- ValueNode x2 = ((CompareNode) conditional.condition()).getX();
- ValueNode y2 = ((CompareNode) conditional.condition()).getY();
+ CompareNode condition2 = (CompareNode) conditional.condition();
+ Condition cond2 = condition2.condition().asCondition();
+ ValueNode x = condition1.getX();
+ ValueNode y = condition1.getY();
+ ValueNode x2 = condition2.getX();
+ ValueNode y2 = condition2.getY();
// `x cond1 y ? c1 : (x2 cond2 y2 ? c2 : c3)`
boolean sameVars = x == x2 && y == y2;
if (!sameVars && x == y2 && y == x2) {
@@ -964,62 +982,89 @@
cond2 = cond2.mirror();
}
if (sameVars) {
+
JavaKind stackKind = conditional.trueValue().stamp(NodeView.from(tool)).getStackKind();
assert !stackKind.isNumericFloat();
- ValueNode v1 = constant;
- ValueNode v2 = conditional.trueValue();
- ValueNode v3 = conditional.falseValue();
+ long c1 = constant.asJavaConstant().asLong();
+ long c2 = conditional.trueValue().asJavaConstant().asLong();
+ long c3 = conditional.falseValue().asJavaConstant().asLong();
- long c1 = v1.asJavaConstant().asLong();
- long c2 = v2.asJavaConstant().asLong();
- long c3 = v3.asJavaConstant().asLong();
+ // canonicalize cond2
+ cond2 = cond2.join(cond1.negate());
+ if (cond2 == null) {
+ // mixing signed and unsigned cases, or useless combination of conditions
+ return null;
+ }
+ // derive cond3 from cond1 and cond2
+ Condition cond3 = cond1.negate().join(cond2.negate());
+ if (cond3 == null) {
+ // mixing signed and unsigned cases, or useless combination of conditions
+ return null;
+ }
+ boolean unsigned = cond1.isUnsigned() || cond2.isUnsigned();
+
+ long expected1 = expectedConstantForNormalize(cond1);
+ long expected2 = expectedConstantForNormalize(cond2);
+ long expected3 = expectedConstantForNormalize(cond3);
- if (cond1 == Condition.LT && cond2 == Condition.EQ && c1 == -1 && c2 == 0 && c3 == 1) {
- // x < y ? -1 : (x == y ? 0 : 1) => x cmp y
- return graph().unique(new NormalizeCompareNode(x, y, stackKind, false));
- } else if (cond1 == Condition.LT && cond2 == Condition.EQ && c1 == 1 && c2 == 0 && c3 == -1) {
- // x < y ? 1 : (x == y ? 0 : -1) => y cmp x
- return graph().unique(new NormalizeCompareNode(y, x, stackKind, false));
- } else if (cond1 == Condition.EQ && cond2 == Condition.LT && c1 == 0 && c2 == -1 && c3 == 1) {
- // x == y ? 0 : (x < y ? -1 : 1) => x cmp y
- return graph().unique(new NormalizeCompareNode(x, y, stackKind, false));
- } else if (cond1 == Condition.EQ && cond2 == Condition.LT && c1 == 0 && c2 == 1 && c3 == -1) {
- // x == y ? 0 : (x < y ? 1 : -1) => y cmp x
- return graph().unique(new NormalizeCompareNode(y, x, stackKind, false));
- } else if (cond1 == Condition.EQ && cond2 == Condition.GT && c1 == 0 && c2 == -1 && c3 == 1) {
- // x == y ? 0 : (x > y ? -1 : 1) => y cmp x
- return graph().unique(new NormalizeCompareNode(y, x, stackKind, false));
- } else if (cond1 == Condition.EQ && cond2 == Condition.GT && c1 == 0 && c2 == 1 && c3 == -1) {
- // x == y ? 0 : (x > y ? 1 : -1) => x cmp y
- return graph().unique(new NormalizeCompareNode(x, y, stackKind, false));
- } else if (cond1 == Condition.LT && cond2 == Condition.GT && c1 == 1 && c2 == -1 && c3 == 0) {
- // x < y ? 1 : (x > y ? -1 : 0) => y cmp x
- return graph().unique(new NormalizeCompareNode(y, x, stackKind, false));
- } else if (cond1 == Condition.LT && cond2 == Condition.GT && c1 == -1 && c2 == 1 && c3 == 0) {
- // x < y ? -1 : (x > y ? 1 : 0) => x cmp y
- return graph().unique(new NormalizeCompareNode(x, y, stackKind, false));
+ if (c1 == expected1 && c2 == expected2 && c3 == expected3) {
+ // normal order
+ } else if (c1 == 0 - expected1 && c2 == 0 - expected2 && c3 == 0 - expected3) {
+ // reverse order
+ ValueNode tmp = x;
+ x = y;
+ y = tmp;
+ } else {
+ // cannot be expressed by NormalizeCompareNode
+ return null;
}
+ if (unsigned) {
+ // for unsigned comparisons, we need to add MIN_VALUE (see
+ // Long.compareUnsigned)
+ ValueNode minValue = graph().unique(ConstantNode.forIntegerStamp(x.stamp,
+ x.stamp.getStackKind().getMinValue()));
+ x = graph().unique(new AddNode(x, minValue));
+ y = graph().unique(new AddNode(y, minValue));
+ }
+ boolean unorderedLess = false;
+ if (x.stamp instanceof FloatStamp && (((FloatStamp) x.stamp).canBeNaN() || ((FloatStamp) y.stamp).canBeNaN())) {
+ // we may encounter NaNs, check the unordered value
+ // (following the original condition's "unorderedIsTrue" path)
+ long unorderedValue = condition1.unorderedIsTrue() ? c1 : condition2.unorderedIsTrue() ? c2 : c3;
+ if (unorderedValue == 0) {
+ // returning "0" for unordered is not possible
+ return null;
+ }
+ unorderedLess = unorderedValue == -1;
+ }
+ return graph().unique(new NormalizeCompareNode(x, y, stackKind, unorderedLess));
}
}
}
return null;
}
+ private static long expectedConstantForNormalize(Condition condition) {
+ if (condition == Condition.EQ) {
+ return 0;
+ } else if (condition == Condition.LT || condition == Condition.BT) {
+ return -1;
+ } else {
+ assert condition == Condition.GT || condition == Condition.AT;
+ return 1;
+ }
+ }
+
/**
* Take an if that is immediately dominated by a merge with a single phi and split off any paths
- * where the test would be statically decidable creating a new merge below the approriate side
+ * where the test would be statically decidable creating a new merge below the appropriate side
* of the IfNode. Any undecidable tests will continue to use the original IfNode.
*
* @param tool
*/
@SuppressWarnings("try")
private boolean splitIfAtPhi(SimplifierTool tool) {
- if (graph().getGuardsStage().areFrameStatesAtSideEffects()) {
- // Disabled until we make sure we have no FrameState-less merges at this stage
- return false;
- }
-
if (!(predecessor() instanceof MergeNode)) {
return false;
}
@@ -1028,15 +1073,14 @@
// Don't bother.
return false;
}
- if (merge.usages().count() != 1 || merge.phis().count() != 1) {
+ if (merge.getUsageCount() != 1 || merge.phis().count() != 1) {
return false;
}
- if (merge.stateAfter() != null) {
- /* We'll get the chance to simplify this after frame state assignment. */
+ if (graph().getGuardsStage().areFrameStatesAtSideEffects() && merge.stateAfter() == null) {
return false;
}
PhiNode phi = merge.phis().first();
- if (phi.usages().count() != 1) {
+ if (phi.getUsageCount() != 1) {
/*
* For simplicity the below code assumes assumes the phi goes dead at the end so skip
* this case.
@@ -1061,7 +1105,6 @@
/* Each successor of the if gets a new merge if needed. */
MergeNode trueMerge = null;
MergeNode falseMerge = null;
- assert merge.stateAfter() == null;
for (EndNode end : merge.forwardEnds().snapshot()) {
Node value = phi.valueAt(end);
@@ -1070,12 +1113,12 @@
merge.removeEnd(end);
if (((LogicConstantNode) result).getValue()) {
if (trueMerge == null) {
- trueMerge = insertMerge(trueSuccessor());
+ trueMerge = insertMerge(trueSuccessor(), merge.stateAfter());
}
trueMerge.addForwardEnd(end);
} else {
if (falseMerge == null) {
- falseMerge = insertMerge(falseSuccessor());
+ falseMerge = insertMerge(falseSuccessor(), merge.stateAfter());
}
falseMerge.addForwardEnd(end);
}
@@ -1096,13 +1139,13 @@
((FixedWithNextNode) end.predecessor()).setNext(newIfNode);
if (trueMerge == null) {
- trueMerge = insertMerge(trueSuccessor());
+ trueMerge = insertMerge(trueSuccessor(), merge.stateAfter());
}
trueBegin.setNext(graph().add(new EndNode()));
trueMerge.addForwardEnd((EndNode) trueBegin.next());
if (falseMerge == null) {
- falseMerge = insertMerge(falseSuccessor());
+ falseMerge = insertMerge(falseSuccessor(), merge.stateAfter());
}
falseBegin.setNext(graph().add(new EndNode()));
falseMerge.addForwardEnd((EndNode) falseBegin.next());
@@ -1129,7 +1172,7 @@
* dead after the optimization.
*/
private static boolean conditionUses(LogicNode condition, PhiNode phi) {
- if (condition.usages().count() != 1) {
+ if (!condition.hasExactlyOneUsage()) {
return false;
}
if (condition instanceof ShortCircuitOrNode) {
@@ -1222,7 +1265,7 @@
}
@SuppressWarnings("try")
- private MergeNode insertMerge(AbstractBeginNode begin) {
+ private MergeNode insertMerge(AbstractBeginNode begin, FrameState stateAfter) {
MergeNode merge = graph().add(new MergeNode());
if (!begin.anchored().isEmpty()) {
Object before = null;
@@ -1245,6 +1288,7 @@
next.replaceAtPredecessor(merge);
theBegin.setNext(graph().add(new EndNode()));
merge.addForwardEnd((EndNode) theBegin.next());
+ merge.setStateAfter(stateAfter);
merge.setNext(next);
return merge;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Fri Jun 28 14:36:42 2019 +0530
@@ -678,7 +678,7 @@
if (node instanceof AbstractBeginNode) {
((AbstractBeginNode) node).prepareDelete();
}
- assert node.hasNoUsages() : node + " " + node.usages().count() + ", " + node.usages().first();
+ assert node.hasNoUsages() : node + " " + node.getUsageCount() + ", " + node.usages().first();
GraphUtil.unlinkFixedNode(node);
node.safeDelete();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ReinterpretNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ReinterpretNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -44,6 +44,7 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.serviceprovider.BufferUtil;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.JavaKind;
@@ -83,7 +84,7 @@
ByteBuffer buffer = ByteBuffer.wrap(new byte[c.getSerializedSize()]).order(ByteOrder.nativeOrder());
c.serialize(buffer);
- buffer.rewind();
+ BufferUtil.asBaseBuffer(buffer).rewind();
SerializableConstant ret = ((ArithmeticStamp) stamp).deserialize(buffer);
assert !buffer.hasRemaining();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -122,7 +122,7 @@
ValueNode dividend = forX;
int log2 = CodeUtil.log2(abs);
// no rounding if dividend is positive or if its low bits are always 0
- if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) {
+ if (stampX.canBeNegative() && (stampX.upMask() & (abs - 1)) != 0) {
int bits = PrimitiveStamp.getBits(forX.stamp(view));
RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1));
UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Fri Jun 28 14:36:42 2019 +0530
@@ -210,7 +210,7 @@
public static void addDeferredExit(DeferredExit[] deferredExits, Block b) {
Loop<Block> outermostExited = b.getDominator().getLoop();
Loop<Block> exitBlockLoop = b.getLoop();
- assert outermostExited != null;
+ assert outermostExited != null : "Dominator must be in a loop. Possible cause is a missing loop exit node.";
while (outermostExited.getParent() != null && outermostExited.getParent() != exitBlockLoop) {
outermostExited = outermostExited.getParent();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ArrayRangeWrite.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,8 +25,8 @@
package org.graalvm.compiler.nodes.extended;
import org.graalvm.compiler.graph.NodeInterface;
-import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.FixedAccessNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
public interface ArrayRangeWrite extends NodeInterface {
@@ -52,5 +52,5 @@
int getElementStride();
@Override
- FixedWithNextNode asNode();
+ FixedAccessNode asNode();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -220,7 +220,7 @@
return false;
}
LoadIndexedNode loadIndexed = (LoadIndexedNode) value();
- if (loadIndexed.usages().count() > 1) {
+ if (loadIndexed.hasMoreThanOneUsage()) {
/*
* The array load is necessary for other reasons too, so there is no benefit optimizing
* the switch.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ArrayRangeWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.spi.Lowerable;
+
+@NodeInfo
+public abstract class ArrayRangeWriteBarrier extends WriteBarrier implements Lowerable {
+
+ public static final NodeClass<ArrayRangeWriteBarrier> TYPE = NodeClass.create(ArrayRangeWriteBarrier.class);
+ @Input ValueNode length;
+
+ private final int elementStride;
+
+ protected ArrayRangeWriteBarrier(NodeClass<? extends ArrayRangeWriteBarrier> c, AddressNode address, ValueNode length, int elementStride) {
+ super(c, address);
+ this.length = length;
+ this.elementStride = elementStride;
+ }
+
+ public ValueNode getLength() {
+ return length;
+ }
+
+ public int getElementStride() {
+ return elementStride;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/BarrierSet.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 org.graalvm.compiler.nodes.gc;
+
+import org.graalvm.compiler.nodes.memory.FixedAccessNode;
+
+public interface BarrierSet {
+ void addBarriers(FixedAccessNode n);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/CardTableBarrierSet.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 org.graalvm.compiler.nodes.gc;
+
+import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
+import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
+import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
+import org.graalvm.compiler.nodes.memory.FixedAccessNode;
+import org.graalvm.compiler.nodes.memory.HeapAccess;
+import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.memory.WriteNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.type.StampTool;
+import org.graalvm.compiler.nodes.util.GraphUtil;
+
+public class CardTableBarrierSet implements BarrierSet {
+ public CardTableBarrierSet() {
+ }
+
+ @Override
+ public void addBarriers(FixedAccessNode n) {
+ if (n instanceof ReadNode) {
+ // nothing to do
+ } else if (n instanceof WriteNode) {
+ WriteNode write = (WriteNode) n;
+ addWriteBarrier(write, write.value());
+ } else if (n instanceof LoweredAtomicReadAndWriteNode) {
+ LoweredAtomicReadAndWriteNode atomic = (LoweredAtomicReadAndWriteNode) n;
+ addWriteBarrier(atomic, atomic.getNewValue());
+ } else if (n instanceof AbstractCompareAndSwapNode) {
+ AbstractCompareAndSwapNode cmpSwap = (AbstractCompareAndSwapNode) n;
+ addWriteBarrier(cmpSwap, cmpSwap.getNewValue());
+ } else if (n instanceof ArrayRangeWrite) {
+ addArrayRangeBarriers((ArrayRangeWrite) n);
+ } else {
+ GraalError.guarantee(n.getBarrierType() == BarrierType.NONE, "missed a node that requires a GC barrier: %s", n.getClass());
+ }
+ }
+
+ public boolean needsBarrier(FixedAccessNode n) {
+ if (n instanceof ReadNode) {
+ return false;
+ } else if (n instanceof WriteNode) {
+ WriteNode write = (WriteNode) n;
+ return needsWriteBarrier(write, write.value());
+ } else if (n instanceof LoweredAtomicReadAndWriteNode) {
+ LoweredAtomicReadAndWriteNode atomic = (LoweredAtomicReadAndWriteNode) n;
+ return needsWriteBarrier(atomic, atomic.getNewValue());
+ } else if (n instanceof AbstractCompareAndSwapNode) {
+ AbstractCompareAndSwapNode cmpSwap = (AbstractCompareAndSwapNode) n;
+ return needsWriteBarrier(cmpSwap, cmpSwap.getNewValue());
+ } else if (n instanceof ArrayRangeWrite) {
+ return needsWriteBarrier((ArrayRangeWrite) n);
+ } else {
+ GraalError.guarantee(n.getBarrierType() == BarrierType.NONE, "missed a node that requires a GC barrier: %s", n.getClass());
+ return false;
+ }
+ }
+
+ public boolean hasBarrier(FixedAccessNode n) {
+ if (n instanceof ReadNode) {
+ return false;
+ } else if (n instanceof WriteNode) {
+ WriteNode write = (WriteNode) n;
+ return hasWriteBarrier(write);
+ } else if (n instanceof LoweredAtomicReadAndWriteNode) {
+ LoweredAtomicReadAndWriteNode atomic = (LoweredAtomicReadAndWriteNode) n;
+ return hasWriteBarrier(atomic);
+ } else if (n instanceof AbstractCompareAndSwapNode) {
+ AbstractCompareAndSwapNode cmpSwap = (AbstractCompareAndSwapNode) n;
+ return hasWriteBarrier(cmpSwap);
+ } else if (n instanceof ArrayRangeWrite) {
+ return hasWriteBarrier((ArrayRangeWrite) n);
+ } else {
+ GraalError.guarantee(n.getBarrierType() == BarrierType.NONE, "missed a node that requires a GC barrier: %s", n.getClass());
+ return false;
+ }
+ }
+
+ public boolean isMatchingBarrier(FixedAccessNode n, WriteBarrier barrier) {
+ if (n instanceof ReadNode) {
+ return false;
+ } else if (n instanceof WriteNode || n instanceof LoweredAtomicReadAndWriteNode || n instanceof AbstractCompareAndSwapNode || n instanceof ArrayRangeWrite) {
+ return barrier instanceof SerialWriteBarrier && matches(n, (SerialWriteBarrier) barrier);
+ } else {
+ throw GraalError.shouldNotReachHere("Unexpected node: " + n.getClass());
+ }
+ }
+
+ public void addArrayRangeBarriers(ArrayRangeWrite write) {
+ if (needsWriteBarrier(write)) {
+ StructuredGraph graph = write.asNode().graph();
+ SerialArrayRangeWriteBarrier serialArrayRangeWriteBarrier = graph.add(new SerialArrayRangeWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
+ graph.addAfterFixed(write.asNode(), serialArrayRangeWriteBarrier);
+ }
+ }
+
+ private void addWriteBarrier(FixedAccessNode node, ValueNode writtenValue) {
+ if (needsWriteBarrier(node, writtenValue)) {
+ addSerialPostWriteBarrier(node, node.getAddress(), node.graph());
+ }
+ }
+
+ public boolean needsWriteBarrier(FixedAccessNode node, ValueNode writtenValue) {
+ assert !(node instanceof ArrayRangeWrite);
+ HeapAccess.BarrierType barrierType = node.getBarrierType();
+ switch (barrierType) {
+ case NONE:
+ return false;
+ case FIELD:
+ case ARRAY:
+ case UNKNOWN:
+ return writeRequiresBarrier(node, writtenValue);
+ default:
+ throw new GraalError("unexpected barrier type: " + barrierType);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ protected boolean writeRequiresBarrier(FixedAccessNode node, ValueNode writtenValue) {
+ // Null writes can skip the card mark.
+ return isNonNullObjectValue(writtenValue);
+ }
+
+ public static boolean needsWriteBarrier(ArrayRangeWrite write) {
+ return write.writesObjectArray();
+ }
+
+ private static boolean hasWriteBarrier(FixedAccessNode node) {
+ return node.next() instanceof SerialWriteBarrier && matches(node, (SerialWriteBarrier) node.next());
+ }
+
+ private static boolean hasWriteBarrier(ArrayRangeWrite write) {
+ FixedAccessNode node = write.asNode();
+ return node.next() instanceof SerialArrayRangeWriteBarrier && matches(write, (SerialArrayRangeWriteBarrier) node.next());
+ }
+
+ private static void addSerialPostWriteBarrier(FixedAccessNode node, AddressNode address, StructuredGraph graph) {
+ boolean precise = node.getBarrierType() != HeapAccess.BarrierType.FIELD;
+ graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(address, precise)));
+ }
+
+ private static boolean isNonNullObjectValue(ValueNode value) {
+ return value.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp && !StampTool.isPointerAlwaysNull(value);
+ }
+
+ private static boolean matches(FixedAccessNode node, SerialWriteBarrier barrier) {
+ if (!barrier.usePrecise()) {
+ if (barrier.getAddress() instanceof OffsetAddressNode && node.getAddress() instanceof OffsetAddressNode) {
+ return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) node.getAddress()).getBase());
+ }
+ }
+ return barrier.getAddress() == node.getAddress();
+ }
+
+ private static boolean matches(ArrayRangeWrite node, SerialArrayRangeWriteBarrier barrier) {
+ return barrier.getAddress() == node.getAddress() && node.getLength() == barrier.getLength() && node.getElementStride() == barrier.getElementStride();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1ArrayRangePostWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
+public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier {
+ public static final NodeClass<G1ArrayRangePostWriteBarrier> TYPE = NodeClass.create(G1ArrayRangePostWriteBarrier.class);
+
+ public G1ArrayRangePostWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
+ super(TYPE, address, length, elementStride);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1ArrayRangePreWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
+public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier {
+ public static final NodeClass<G1ArrayRangePreWriteBarrier> TYPE = NodeClass.create(G1ArrayRangePreWriteBarrier.class);
+
+ public G1ArrayRangePreWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
+ super(TYPE, address, length, elementStride);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1BarrierSet.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 org.graalvm.compiler.nodes.gc;
+
+import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
+import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
+import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
+import org.graalvm.compiler.nodes.memory.FixedAccessNode;
+import org.graalvm.compiler.nodes.memory.HeapAccess;
+import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.memory.WriteNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.type.StampTool;
+
+public class G1BarrierSet implements BarrierSet {
+ public G1BarrierSet() {
+ }
+
+ @Override
+ public void addBarriers(FixedAccessNode n) {
+ if (n instanceof ReadNode) {
+ addReadNodeBarriers((ReadNode) n);
+ } else if (n instanceof WriteNode) {
+ WriteNode write = (WriteNode) n;
+ addWriteBarriers(write, write.value(), null, true, write.getNullCheck());
+ } else if (n instanceof LoweredAtomicReadAndWriteNode) {
+ LoweredAtomicReadAndWriteNode atomic = (LoweredAtomicReadAndWriteNode) n;
+ addWriteBarriers(atomic, atomic.getNewValue(), null, true, atomic.getNullCheck());
+ } else if (n instanceof AbstractCompareAndSwapNode) {
+ AbstractCompareAndSwapNode cmpSwap = (AbstractCompareAndSwapNode) n;
+ addWriteBarriers(cmpSwap, cmpSwap.getNewValue(), cmpSwap.getExpectedValue(), false, false);
+ } else if (n instanceof ArrayRangeWrite) {
+ addArrayRangeBarriers((ArrayRangeWrite) n);
+ } else {
+ GraalError.guarantee(n.getBarrierType() == BarrierType.NONE, "missed a node that requires a GC barrier: %s", n.getClass());
+ }
+ }
+
+ private static void addReadNodeBarriers(ReadNode node) {
+ if (node.getBarrierType() == HeapAccess.BarrierType.WEAK_FIELD) {
+ StructuredGraph graph = node.graph();
+ G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.getAddress(), node, false));
+ graph.addAfterFixed(node, barrier);
+ }
+ }
+
+ private void addWriteBarriers(FixedAccessNode node, ValueNode writtenValue, ValueNode expectedValue, boolean doLoad, boolean nullCheck) {
+ HeapAccess.BarrierType barrierType = node.getBarrierType();
+ switch (barrierType) {
+ case NONE:
+ // nothing to do
+ break;
+ case FIELD:
+ case ARRAY:
+ case UNKNOWN:
+ if (isObjectValue(writtenValue)) {
+ StructuredGraph graph = node.graph();
+ boolean init = node.getLocationIdentity().isInit();
+ if (!init) {
+ // The pre barrier does nothing if the value being read is null, so it can
+ // be explicitly skipped when this is an initializing store.
+ addG1PreWriteBarrier(node, node.getAddress(), expectedValue, doLoad, nullCheck, graph);
+ }
+ if (writeRequiresPostBarrier(node, writtenValue)) {
+ boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
+ addG1PostWriteBarrier(node, node.getAddress(), writtenValue, precise, graph);
+ }
+ }
+ break;
+ default:
+ throw new GraalError("unexpected barrier type: " + barrierType);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ protected boolean writeRequiresPostBarrier(FixedAccessNode initializingWrite, ValueNode writtenValue) {
+ // Without help from the runtime all writes require an explicit post barrier.
+ return true;
+ }
+
+ private static void addArrayRangeBarriers(ArrayRangeWrite write) {
+ if (write.writesObjectArray()) {
+ StructuredGraph graph = write.asNode().graph();
+ if (!write.isInitialization()) {
+ // The pre barrier does nothing if the value being read is null, so it can
+ // be explicitly skipped when this is an initializing store.
+ G1ArrayRangePreWriteBarrier g1ArrayRangePreWriteBarrier = graph.add(new G1ArrayRangePreWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
+ graph.addBeforeFixed(write.asNode(), g1ArrayRangePreWriteBarrier);
+ }
+ G1ArrayRangePostWriteBarrier g1ArrayRangePostWriteBarrier = graph.add(new G1ArrayRangePostWriteBarrier(write.getAddress(), write.getLength(), write.getElementStride()));
+ graph.addAfterFixed(write.asNode(), g1ArrayRangePostWriteBarrier);
+ }
+ }
+
+ private static void addG1PreWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean doLoad, boolean nullCheck, StructuredGraph graph) {
+ G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(address, value, doLoad, nullCheck));
+ preBarrier.setStateBefore(node.stateBefore());
+ node.setNullCheck(false);
+ node.setStateBefore(null);
+ graph.addBeforeFixed(node, preBarrier);
+ }
+
+ private static void addG1PostWriteBarrier(FixedAccessNode node, AddressNode address, ValueNode value, boolean precise, StructuredGraph graph) {
+ final boolean alwaysNull = StampTool.isPointerAlwaysNull(value);
+ graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(address, value, precise, alwaysNull)));
+ }
+
+ private static boolean isObjectValue(ValueNode value) {
+ return value.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1PostWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
+public class G1PostWriteBarrier extends ObjectWriteBarrier {
+
+ public static final NodeClass<G1PostWriteBarrier> TYPE = NodeClass.create(G1PostWriteBarrier.class);
+ protected final boolean alwaysNull;
+
+ public G1PostWriteBarrier(AddressNode address, ValueNode value, boolean precise, boolean alwaysNull) {
+ this(TYPE, address, value, precise, alwaysNull);
+ }
+
+ private G1PostWriteBarrier(NodeClass<? extends G1PostWriteBarrier> c, AddressNode address, ValueNode value, boolean precise, boolean alwaysNull) {
+ super(c, address, value, precise);
+ this.alwaysNull = alwaysNull;
+ }
+
+ public boolean alwaysNull() {
+ return alwaysNull;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1PreWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.DeoptimizingNode;
+import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
+public final class G1PreWriteBarrier extends ObjectWriteBarrier implements DeoptimizingNode.DeoptBefore {
+
+ public static final NodeClass<G1PreWriteBarrier> TYPE = NodeClass.create(G1PreWriteBarrier.class);
+
+ @OptionalInput(InputType.State) private FrameState stateBefore;
+ private final boolean nullCheck;
+ private final boolean doLoad;
+
+ public G1PreWriteBarrier(AddressNode address, ValueNode expectedObject, boolean doLoad, boolean nullCheck) {
+ super(TYPE, address, expectedObject, true);
+ assert doLoad == (expectedObject == null);
+ this.doLoad = doLoad;
+ this.nullCheck = nullCheck;
+ }
+
+ public ValueNode getExpectedObject() {
+ return getValue();
+ }
+
+ public boolean doLoad() {
+ return doLoad;
+ }
+
+ public boolean getNullCheck() {
+ return nullCheck;
+ }
+
+ @Override
+ public boolean canDeoptimize() {
+ return nullCheck;
+ }
+
+ @Override
+ public FrameState stateBefore() {
+ return stateBefore;
+ }
+
+ @Override
+ public void setStateBefore(FrameState state) {
+ updateUsages(stateBefore, state);
+ stateBefore = state;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/G1ReferentFieldReadBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+/**
+ * The {@code G1ReferentFieldReadBarrier} is added when a read access is performed to the referent
+ * field of a {@link java.lang.ref.Reference} object (through a {@code LoadFieldNode} or an
+ * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the
+ * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled.
+ */
+@NodeInfo(cycles = CYCLES_64, size = SIZE_64)
+public final class G1ReferentFieldReadBarrier extends ObjectWriteBarrier {
+ public static final NodeClass<G1ReferentFieldReadBarrier> TYPE = NodeClass.create(G1ReferentFieldReadBarrier.class);
+
+ private final boolean doLoad;
+
+ public G1ReferentFieldReadBarrier(AddressNode address, ValueNode expectedObject, boolean doLoad) {
+ super(TYPE, address, expectedObject, true);
+ this.doLoad = doLoad;
+ }
+
+ public ValueNode getExpectedObject() {
+ return getValue();
+ }
+
+ public boolean doLoad() {
+ return doLoad;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ObjectWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+@NodeInfo
+public abstract class ObjectWriteBarrier extends WriteBarrier {
+
+ public static final NodeClass<ObjectWriteBarrier> TYPE = NodeClass.create(ObjectWriteBarrier.class);
+ @OptionalInput protected ValueNode value;
+ protected final boolean precise;
+
+ protected ObjectWriteBarrier(NodeClass<? extends ObjectWriteBarrier> c, AddressNode address, ValueNode value, boolean precise) {
+ super(c, address);
+ this.value = value;
+ this.precise = precise;
+ }
+
+ public ValueNode getValue() {
+ return value;
+ }
+
+ public boolean usePrecise() {
+ return precise;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialArrayRangeWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+@NodeInfo(cycles = CYCLES_8, size = SIZE_8)
+public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier {
+ public static final NodeClass<SerialArrayRangeWriteBarrier> TYPE = NodeClass.create(SerialArrayRangeWriteBarrier.class);
+
+ public SerialArrayRangeWriteBarrier(AddressNode address, ValueNode length, int elementStride) {
+ super(TYPE, address, length, elementStride);
+ }
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialWriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+
+@NodeInfo(cycles = CYCLES_8, size = SIZE_4)
+public class SerialWriteBarrier extends ObjectWriteBarrier {
+ public static final NodeClass<SerialWriteBarrier> TYPE = NodeClass.create(SerialWriteBarrier.class);
+
+ protected boolean verifyOnly;
+
+ public SerialWriteBarrier(AddressNode address, boolean precise) {
+ this(TYPE, address, precise);
+ }
+
+ protected SerialWriteBarrier(NodeClass<? extends SerialWriteBarrier> c, AddressNode address, boolean precise) {
+ super(c, address, null, precise);
+ }
+
+ public void setVerifyOnly(boolean value) {
+ this.verifyOnly = value;
+ }
+
+ public boolean getVerifyOnly() {
+ return verifyOnly;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/WriteBarrier.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.gc;
+
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.FixedWithNextNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.spi.Lowerable;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+
+@NodeInfo
+public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable {
+
+ public static final NodeClass<WriteBarrier> TYPE = NodeClass.create(WriteBarrier.class);
+ @Input(InputType.Association) AddressNode address;
+
+ protected WriteBarrier(NodeClass<? extends WriteBarrier> c, AddressNode address) {
+ super(c, StampFactory.forVoid());
+ this.address = address;
+ }
+
+ @Override
+ public void lower(LoweringTool tool) {
+ assert graph().getGuardsStage().areFrameStatesAtDeopts();
+ tool.getLowerer().lower(this, tool);
+ }
+
+ public AddressNode getAddress() {
+ return address;
+ }
+}
+
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java Fri Jun 28 14:36:42 2019 +0530
@@ -192,7 +192,12 @@
if (!IS_IN_NATIVE_IMAGE && UseEncodedGraphs.getValue(b.getOptions())) {
b.getReplacements().registerMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, b.getOptions());
}
- StructuredGraph subst = b.getReplacements().getMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, StructuredGraph.AllowAssumptions.ifNonNull(b.getAssumptions()), b.getOptions());
+ StructuredGraph subst = b.getReplacements().getMethodSubstitution(this,
+ targetMethod,
+ INLINE_AFTER_PARSING,
+ StructuredGraph.AllowAssumptions.ifNonNull(b.getAssumptions()),
+ null /* cancellable */,
+ b.getOptions());
if (subst == null) {
throw new GraalError("No graphs found for substitution %s", this);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -274,4 +274,8 @@
}
return null;
}
+
+ public void setJavaTypeProfile(JavaTypeProfile profile) {
+ this.profile = profile;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@
super(c, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
}
- public abstract FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess);
+ public abstract FloatingAccessNode asFloatingNode();
protected boolean forceFixed;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
package org.graalvm.compiler.nodes.memory;
+import static org.graalvm.compiler.nodeinfo.InputType.Memory;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import static org.graalvm.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION;
@@ -43,6 +44,7 @@
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.ValueNodeUtil;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
@@ -60,10 +62,12 @@
* Reads an {@linkplain FixedAccessNode accessed} value.
*/
@NodeInfo(nameTemplate = "Read#{p#location/s}", cycles = CYCLES_2, size = SIZE_1)
-public class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, Canonicalizable, Virtualizable, GuardingNode {
+public class ReadNode extends FloatableAccessNode implements LIRLowerableAccess, Canonicalizable, Virtualizable, GuardingNode, MemoryAccess {
public static final NodeClass<ReadNode> TYPE = NodeClass.create(ReadNode.class);
+ @OptionalInput(Memory) MemoryNode lastLocationAccess;
+
public ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, BarrierType barrierType) {
this(TYPE, address, location, stamp, null, barrierType, false, null);
}
@@ -71,6 +75,18 @@
protected ReadNode(NodeClass<? extends ReadNode> c, AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
FrameState stateBefore) {
super(c, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
+ this.lastLocationAccess = null;
+ }
+
+ @Override
+ public MemoryNode getLastLocationAccess() {
+ return lastLocationAccess;
+ }
+
+ @Override
+ public void setLastLocationAccess(MemoryNode newlla) {
+ updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(newlla));
+ lastLocationAccess = newlla;
}
@Override
@@ -96,7 +112,7 @@
@SuppressWarnings("try")
@Override
- public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) {
+ public FloatingAccessNode asFloatingNode() {
try (DebugCloseable position = withNodeSourcePosition()) {
return graph().unique(new FloatingReadNode(getAddress(), getLocationIdentity(), lastLocationAccess, stamp(NodeView.DEFAULT), getGuard(), getBarrierType()));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/IndexAddressNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/IndexAddressNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,12 +43,18 @@
@Input ValueNode array;
@Input ValueNode index;
+ private final JavaKind arrayKind;
private final JavaKind elementKind;
public IndexAddressNode(ValueNode array, ValueNode index, JavaKind elementKind) {
+ this(array, index, elementKind, elementKind);
+ }
+
+ public IndexAddressNode(ValueNode array, ValueNode index, JavaKind arrayKind, JavaKind elementKind) {
super(TYPE);
this.array = array;
this.index = index;
+ this.arrayKind = arrayKind;
this.elementKind = elementKind;
}
@@ -71,6 +77,10 @@
return Long.MAX_VALUE;
}
+ public JavaKind getArrayKind() {
+ return arrayKind;
+ }
+
public JavaKind getElementKind() {
return elementKind;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProviders.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProviders.java Fri Jun 28 14:36:42 2019 +0530
@@ -45,4 +45,6 @@
StampProvider getStampProvider();
ForeignCallsProvider getForeignCalls();
+
+ GCProvider getGC();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersDelegate.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.spi;
+
+import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
+import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
+
+public class CoreProvidersDelegate implements CoreProviders {
+
+ private final CoreProviders providers;
+
+ protected CoreProvidersDelegate(CoreProviders providers) {
+ this.providers = providers;
+ }
+
+ @Override
+ public MetaAccessProvider getMetaAccess() {
+ return providers.getMetaAccess();
+ }
+
+ @Override
+ public ConstantReflectionProvider getConstantReflection() {
+ return providers.getConstantReflection();
+ }
+
+ @Override
+ public ConstantFieldProvider getConstantFieldProvider() {
+ return providers.getConstantFieldProvider();
+ }
+
+ @Override
+ public LoweringProvider getLowerer() {
+ return providers.getLowerer();
+ }
+
+ @Override
+ public Replacements getReplacements() {
+ return providers.getReplacements();
+ }
+
+ @Override
+ public StampProvider getStampProvider() {
+ return providers.getStampProvider();
+ }
+
+ @Override
+ public ForeignCallsProvider getForeignCalls() {
+ return providers.getForeignCalls();
+ }
+
+ @Override
+ public GCProvider getGC() {
+ return providers.getGC();
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersImpl.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersImpl.java Fri Jun 28 14:36:42 2019 +0530
@@ -38,9 +38,10 @@
protected final Replacements replacements;
protected final StampProvider stampProvider;
protected final ForeignCallsProvider foreignCalls;
+ protected final GCProvider gc;
protected CoreProvidersImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, LoweringProvider lowerer,
- Replacements replacements, StampProvider stampProvider, ForeignCallsProvider foreignCalls) {
+ Replacements replacements, StampProvider stampProvider, ForeignCallsProvider foreignCalls, GCProvider gc) {
this.metaAccess = metaAccess;
this.constantReflection = constantReflection;
this.constantFieldProvider = constantFieldProvider;
@@ -48,6 +49,7 @@
this.replacements = replacements;
this.stampProvider = stampProvider;
this.foreignCalls = foreignCalls;
+ this.gc = gc;
}
@Override
@@ -84,4 +86,9 @@
public ForeignCallsProvider getForeignCalls() {
return foreignCalls;
}
+
+ @Override
+ public GCProvider getGC() {
+ return gc;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,6 +29,7 @@
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.NodeSourcePosition;
+import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
@@ -76,8 +77,8 @@
@Override
public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
- StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
- return delegate.getMethodSubstitution(plugin, original, context, allowAssumptions, options);
+ StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) {
+ return delegate.getMethodSubstitution(plugin, original, context, allowAssumptions, cancellable, options);
}
@Override
@@ -91,8 +92,8 @@
}
@Override
- public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) {
- return delegate.getIntrinsicGraph(method, compilationId, debug);
+ public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug, Cancellable cancellable) {
+ return delegate.getIntrinsicGraph(method, compilationId, debug, cancellable);
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/GCProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.nodes.spi;
+
+import org.graalvm.compiler.nodes.gc.BarrierSet;
+
+public interface GCProvider {
+ /** Returns the barrier set that is used to insert the needed read/write barriers. */
+ BarrierSet getBarrierSet();
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java Fri Jun 28 14:36:42 2019 +0530
@@ -30,6 +30,7 @@
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.NodeSourcePosition;
+import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
@@ -86,11 +87,12 @@
* @param original the method being substituted
* @param context the kind of inlining to be performed for the substitution
* @param allowAssumptions
+ * @param cancellable
* @param options
* @return the method substitution graph, if any, that is derived from {@code method}
*/
StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
- StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options);
+ StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options);
/**
* Registers a plugin as a substitution.
@@ -115,9 +117,10 @@
* @param method
* @param compilationId
* @param debug
+ * @param cancellable
* @return an intrinsic graph that can be compiled and installed for {@code method} or null
*/
- StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug);
+ StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug, Cancellable cancellable);
/**
* Determines if there may be a
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/Option.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/Option.java Fri Jun 28 14:36:42 2019 +0530
@@ -64,4 +64,9 @@
* Specifies the type of the option.
*/
OptionType type() default OptionType.Debug;
+
+ /**
+ * Specifies the stability of the option.
+ */
+ OptionStability stability() default OptionStability.EXPERIMENTAL;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionStability.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.options;
+
+/**
+ * Categorizes options according to their stability.
+ */
+public enum OptionStability {
+
+ /**
+ * A stable option is expected to remain available for many releases. End users can rely on such
+ * an option being present. A stable option can still be removed but will go through a clear
+ * deprecating process before being removed.
+ */
+ STABLE,
+
+ /**
+ * An experimental option has no guarantees of stability and might be removed at any point.
+ */
+ EXPERIMENTAL
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Fri Jun 28 14:36:42 2019 +0530
@@ -67,15 +67,12 @@
*/
loader = ClassLoader.getSystemClassLoader();
}
- Iterable<OptionDescriptors> result = ServiceLoader.load(OptionDescriptors.class, loader);
- if (IS_BUILDING_NATIVE_IMAGE) {
- ArrayList<OptionDescriptors> optionDescriptors = new ArrayList<>();
- for (OptionDescriptors descriptors : result) {
- optionDescriptors.add(descriptors);
- }
- OptionsParser.cachedOptionDescriptors = optionDescriptors;
- }
- return result;
+ return ServiceLoader.load(OptionDescriptors.class, loader);
+ }
+
+ public static void setCachedOptionDescriptors(List<OptionDescriptors> cachedOptionDescriptors) {
+ assert IS_BUILDING_NATIVE_IMAGE : "Used to pre-initialize the option descriptors during native image generation";
+ OptionsParser.cachedOptionDescriptors = cachedOptionDescriptors;
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -42,6 +42,7 @@
import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.ControlSinkNode;
@@ -52,18 +53,18 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.Phase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
-public class CanonicalizerPhase extends BasePhase<PhaseContext> {
+public class CanonicalizerPhase extends BasePhase<CoreProviders> {
private static final int MAX_ITERATION_PER_NODE = 10;
private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes");
@@ -121,7 +122,7 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
new Instance(context).run(graph);
}
@@ -129,11 +130,11 @@
* @param newNodesMark only the {@linkplain Graph#getNewNodes(Mark) new nodes} specified by this
* mark are processed
*/
- public void applyIncremental(StructuredGraph graph, PhaseContext context, Mark newNodesMark) {
+ public void applyIncremental(StructuredGraph graph, CoreProviders context, Mark newNodesMark) {
applyIncremental(graph, context, newNodesMark, true);
}
- public void applyIncremental(StructuredGraph graph, PhaseContext context, Mark newNodesMark, boolean dumpGraph) {
+ public void applyIncremental(StructuredGraph graph, CoreProviders context, Mark newNodesMark, boolean dumpGraph) {
new Instance(context, newNodesMark).apply(graph, dumpGraph);
}
@@ -141,19 +142,19 @@
* @param workingSet the initial working set of nodes on which the canonicalizer works, should
* be an auto-grow node bitmap
*/
- public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<? extends Node> workingSet) {
+ public void applyIncremental(StructuredGraph graph, CoreProviders context, Iterable<? extends Node> workingSet) {
applyIncremental(graph, context, workingSet, true);
}
- public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<? extends Node> workingSet, boolean dumpGraph) {
+ public void applyIncremental(StructuredGraph graph, CoreProviders context, Iterable<? extends Node> workingSet, boolean dumpGraph) {
new Instance(context, workingSet).apply(graph, dumpGraph);
}
- public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<? extends Node> workingSet, Mark newNodesMark) {
+ public void applyIncremental(StructuredGraph graph, CoreProviders context, Iterable<? extends Node> workingSet, Mark newNodesMark) {
applyIncremental(graph, context, workingSet, newNodesMark, true);
}
- public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<? extends Node> workingSet, Mark newNodesMark, boolean dumpGraph) {
+ public void applyIncremental(StructuredGraph graph, CoreProviders context, Iterable<? extends Node> workingSet, Mark newNodesMark, boolean dumpGraph) {
new Instance(context, workingSet, newNodesMark).apply(graph, dumpGraph);
}
@@ -164,26 +165,26 @@
private final class Instance extends Phase {
private final Mark newNodesMark;
- private final PhaseContext context;
+ private final CoreProviders context;
private final Iterable<? extends Node> initWorkingSet;
private NodeWorkList workList;
private Tool tool;
private DebugContext debug;
- private Instance(PhaseContext context) {
+ private Instance(CoreProviders context) {
this(context, null, null);
}
- private Instance(PhaseContext context, Iterable<? extends Node> workingSet) {
+ private Instance(CoreProviders context, Iterable<? extends Node> workingSet) {
this(context, workingSet, null);
}
- private Instance(PhaseContext context, Mark newNodesMark) {
+ private Instance(CoreProviders context, Mark newNodesMark) {
this(context, null, newNodesMark);
}
- private Instance(PhaseContext context, Iterable<? extends Node> workingSet, Mark newNodesMark) {
+ private Instance(CoreProviders context, Iterable<? extends Node> workingSet, Mark newNodesMark) {
this.newNodesMark = newNodesMark;
this.context = context;
this.initWorkingSet = workingSet;
@@ -207,12 +208,14 @@
if (!wholeGraph) {
workList.addAll(graph.getNewNodes(newNodesMark));
}
+
tool = new Tool(graph.getAssumptions(), graph.getOptions());
processWorkSet(graph);
}
@SuppressWarnings("try")
- private void processWorkSet(StructuredGraph graph) {
+ private int processWorkSet(StructuredGraph graph) {
+ int sum = 0;
NodeEventListener listener = new NodeEventListener() {
@Override
@@ -228,6 +231,13 @@
workList.add(usage);
}
}
+
+ if (node instanceof AbstractBeginNode) {
+ AbstractBeginNode abstractBeginNode = (AbstractBeginNode) node;
+ if (abstractBeginNode.predecessor() != null) {
+ workList.add(abstractBeginNode.predecessor());
+ }
+ }
}
@Override
@@ -242,8 +252,10 @@
if (changed && debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) {
debug.dump(DebugContext.DETAILED_LEVEL, graph, "CanonicalizerPhase %s", n);
}
+ ++sum;
}
}
+ return sum;
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -56,6 +56,7 @@
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.BinaryOpLogicNode;
import org.graalvm.compiler.nodes.ConditionAnchorNode;
+import org.graalvm.compiler.nodes.DeoptimizeNode;
import org.graalvm.compiler.nodes.DeoptimizingGuard;
import org.graalvm.compiler.nodes.EndNode;
import org.graalvm.compiler.nodes.FixedGuardNode;
@@ -90,20 +91,20 @@
import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
import org.graalvm.compiler.nodes.java.InstanceOfNode;
import org.graalvm.compiler.nodes.java.TypeSwitchNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.NodeWithState;
import org.graalvm.compiler.nodes.spi.StampInverter;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.SpeculationLog.Speculation;
import jdk.vm.ci.meta.TriState;
-public class ConditionalEliminationPhase extends BasePhase<PhaseContext> {
+public class ConditionalEliminationPhase extends BasePhase<CoreProviders> {
private static final CounterKey counterStampsRegistered = DebugContext.counter("StampsRegistered");
private static final CounterKey counterStampsFound = DebugContext.counter("StampsFound");
@@ -123,7 +124,7 @@
@Override
@SuppressWarnings("try")
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
try (DebugContext.Scope s = graph.getDebug().scope("DominatorConditionalElimination")) {
BlockMap<List<Node>> blockToNodes = null;
NodeMap<Block> nodeToBlock = null;
@@ -154,7 +155,7 @@
}
protected ControlFlowGraph.RecursiveVisitor<?> createVisitor(StructuredGraph graph, @SuppressWarnings("unused") ControlFlowGraph cfg, BlockMap<List<Node>> blockToNodes,
- NodeMap<Block> nodeToBlock, PhaseContext context) {
+ NodeMap<Block> nodeToBlock, CoreProviders context) {
return new Instance(graph, blockToNodes, nodeToBlock, context);
}
@@ -302,7 +303,7 @@
*/
private Deque<DeoptimizingGuard> pendingTests;
- public Instance(StructuredGraph graph, BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, PhaseContext context) {
+ public Instance(StructuredGraph graph, BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, CoreProviders context) {
this.graph = graph;
this.debug = graph.getDebug();
this.blockToNodes = blockToNodes;
@@ -335,19 +336,26 @@
if (!tryProveGuardCondition(node, node.getCondition(), (guard, result, guardedValueStamp, newInput) -> {
if (result != node.isNegated()) {
node.replaceAndDelete(guard.asNode());
+ if (guard instanceof DeoptimizingGuard && !((DeoptimizingGuard) guard).isNegated()) {
+ rebuildPiNodes((DeoptimizingGuard) guard);
+ }
} else {
- /*
- * Don't kill this branch immediately because `killCFG` can have complex
- * implications in the presence of loops: it might replace or delete nodes in
- * other branches or even above the kill point. Instead of killing immediately,
- * just leave the graph in a state that is easy to simplify by a subsequent
- * canonicalizer phase.
- */
- FixedGuardNode deopt = new FixedGuardNode(LogicConstantNode.forBoolean(result, node.graph()), node.getReason(), node.getAction(), node.getSpeculation(), node.isNegated(),
- node.getNodeSourcePosition());
AbstractBeginNode beginNode = (AbstractBeginNode) node.getAnchor();
- graph.addAfterFixed(beginNode, node.graph().add(deopt));
+ if (beginNode.next() instanceof DeoptimizeNode) {
+ // This branch is already dead.
+ } else {
+ /*
+ * Don't kill this branch immediately because `killCFG` can have complex
+ * implications in the presence of loops: it might replace or delete nodes
+ * in other branches or even above the kill point. Instead of killing
+ * immediately, just leave the graph in a state that is easy to simplify by
+ * a subsequent canonicalizer phase.
+ */
+ FixedGuardNode deopt = new FixedGuardNode(LogicConstantNode.forBoolean(result, node.graph()), node.getReason(), node.getAction(), node.getSpeculation(), node.isNegated(),
+ node.getNodeSourcePosition());
+ graph.addAfterFixed(beginNode, node.graph().add(deopt));
+ }
}
return true;
})) {
@@ -361,41 +369,14 @@
node.replaceAtUsages(guard.asNode());
GraphUtil.unlinkFixedNode(node);
GraphUtil.killWithUnusedFloatingInputs(node);
+ if (guard instanceof DeoptimizingGuard && !((DeoptimizingGuard) guard).isNegated()) {
+ rebuildPiNodes((DeoptimizingGuard) guard);
+ }
} else {
node.setCondition(LogicConstantNode.forBoolean(result, node.graph()), node.isNegated());
// Don't kill this branch immediately, see `processGuard`.
}
- if (guard instanceof DeoptimizingGuard && !node.isNegated() && !((DeoptimizingGuard) guard).isNegated()) {
- LogicNode newCondition = ((DeoptimizingGuard) guard.asNode()).getCondition();
- if (newCondition instanceof InstanceOfNode) {
- InstanceOfNode inst = (InstanceOfNode) newCondition;
- ValueNode originalValue = GraphUtil.skipPi(inst.getValue());
- PiNode pi = null;
- // Ensure that any Pi that's weaker than what the instanceof proves is
- // replaced by one derived from the instanceof itself.
- for (PiNode existing : guard.asNode().usages().filter(PiNode.class).snapshot()) {
- if (!existing.isAlive()) {
- continue;
- }
- if (originalValue != GraphUtil.skipPi(existing.object())) {
- // Somehow these are unrelated values so leave it alone
- continue;
- }
- // If the pi has a weaker stamp or the same stamp but a different input
- // then replace it.
- boolean strongerStamp = !existing.piStamp().join(inst.getCheckedStamp()).equals(inst.getCheckedStamp());
- boolean differentStamp = !existing.piStamp().equals(inst.getCheckedStamp());
- boolean differentObject = existing.object() != inst.getValue();
- if (!strongerStamp && (differentStamp || differentObject)) {
- if (pi == null) {
- pi = graph.unique(new PiNode(inst.getValue(), inst.getCheckedStamp(), (ValueNode) guard));
- }
- existing.replaceAndDelete(pi);
- }
- }
- }
- }
debug.log("Kill fixed guard %s", node);
return true;
})) {
@@ -403,6 +384,59 @@
}
}
+ private void rebuildPiNodes(DeoptimizingGuard guard) {
+ LogicNode newCondition = guard.getCondition();
+ if (newCondition instanceof InstanceOfNode) {
+ InstanceOfNode inst = (InstanceOfNode) newCondition;
+ ValueNode originalValue = GraphUtil.skipPi(inst.getValue());
+ PiNode pi = null;
+ // Ensure that any Pi that's weaker than what the instanceof proves is
+ // replaced by one derived from the instanceof itself.
+ for (PiNode existing : guard.asNode().usages().filter(PiNode.class).snapshot()) {
+ if (!existing.isAlive()) {
+ continue;
+ }
+ if (originalValue != GraphUtil.skipPi(existing.object())) {
+ // Somehow these are unrelated values so leave it alone
+ continue;
+ }
+ // If the pi has a weaker stamp or the same stamp but a different input
+ // then replace it.
+ boolean strongerStamp = !existing.piStamp().join(inst.getCheckedStamp()).equals(inst.getCheckedStamp());
+ boolean differentCheckedStamp = !existing.piStamp().equals(inst.getCheckedStamp());
+ boolean differentObject = existing.object() != inst.getValue();
+ if (!strongerStamp && (differentCheckedStamp || differentObject)) {
+ if (pi == null) {
+ pi = graph.unique(new PiNode(inst.getValue(), inst.getCheckedStamp(), (ValueNode) guard));
+ }
+ if (!pi.stamp(NodeView.DEFAULT).join(existing.stamp(NodeView.DEFAULT)).equals(pi.stamp(NodeView.DEFAULT))) {
+ /*
+ * With a code sequence like null check, type check, null check of type
+ * checked value, CE will use the first null check to prove the second
+ * null check so the graph ends up a Pi guarded by the first null check
+ * but consuming the output Pi from the type check check. In this case
+ * we should still canonicalize the checked stamp for consistency.
+ */
+ if (differentCheckedStamp) {
+ PiNode alternatePi = graph.unique(new PiNode(existing.object(), inst.getCheckedStamp(), (ValueNode) guard));
+ /*
+ * If the resulting stamp is as good or better then do the
+ * replacement. However when interface types are involved it's
+ * possible that improving the checked stamp merges types which
+ * appear unrelated so there's we must skip the replacement.
+ */
+ if (alternatePi.stamp(NodeView.DEFAULT).join(existing.stamp(NodeView.DEFAULT)).equals(alternatePi.stamp(NodeView.DEFAULT))) {
+ existing.replaceAndDelete(alternatePi);
+ }
+ }
+ continue;
+ }
+ existing.replaceAndDelete(pi);
+ }
+ }
+ }
+ }
+
protected void processIf(IfNode node) {
tryProveCondition(node.condition(), (guard, result, guardedValueStamp, newInput) -> {
node.setCondition(LogicConstantNode.forBoolean(result, node.graph()));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -69,6 +69,7 @@
import org.graalvm.compiler.nodes.memory.FloatingReadNode;
import org.graalvm.compiler.nodes.memory.MemoryAccess;
import org.graalvm.compiler.nodes.memory.MemoryPhiNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
@@ -77,7 +78,6 @@
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
import org.graalvm.compiler.phases.tiers.LowTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.Constant;
@@ -638,7 +638,7 @@
}
}
- protected ControlFlowGraph.RecursiveVisitor<?> createVisitor(StructuredGraph graph, ScheduleResult schedule, PhaseContext context) {
+ protected ControlFlowGraph.RecursiveVisitor<?> createVisitor(StructuredGraph graph, ScheduleResult schedule, CoreProviders context) {
return new RawConditionalEliminationVisitor(graph, schedule, context.getMetaAccess(), replaceInputsWithConstants);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -381,7 +381,8 @@
assert accessNode.getNullCheck() == false;
MemoryNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
try (DebugCloseable position = accessNode.withNodeSourcePosition()) {
- FloatingAccessNode floatingNode = accessNode.asFloatingNode(lastLocationAccess);
+ FloatingAccessNode floatingNode = accessNode.asFloatingNode();
+ assert floatingNode.getLastLocationAccess() == lastLocationAccess;
graph.replaceFixedWithFloating(accessNode, floatingNode);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/IncrementalCanonicalizerPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/IncrementalCanonicalizerPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -26,16 +26,16 @@
import org.graalvm.compiler.graph.Graph.NodeEventScope;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
/**
* A phase suite that applies {@linkplain CanonicalizerPhase canonicalization} to a graph after all
* phases in the suite have been applied if any of the phases changed the graph.
*/
-public class IncrementalCanonicalizerPhase<C extends PhaseContext> extends PhaseSuite<C> {
+public class IncrementalCanonicalizerPhase<C extends CoreProviders> extends PhaseSuite<C> {
private final CanonicalizerPhase canonicalizer;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/IterativeConditionalEliminationPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/IterativeConditionalEliminationPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,20 +24,21 @@
package org.graalvm.compiler.phases.common;
-import static org.graalvm.compiler.graph.Graph.NodeEvent.NODE_ADDED;
-
-import org.graalvm.compiler.core.common.RetryableBailoutException;
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.core.common.PermanentBailoutException;
+import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.graph.spi.Simplifiable;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.graalvm.compiler.phases.common.util.TracingNodeEventListener;
-public class IterativeConditionalEliminationPhase extends BasePhase<PhaseContext> {
+public class IterativeConditionalEliminationPhase extends BasePhase<CoreProviders> {
- private static final int MAX_ITERATIONS = 256;
+ private static final boolean DEBUG_PHASE = false;
+ private static final int DEBUG_MAX_ITERATIONS = 256;
private final CanonicalizerPhase canonicalizer;
private final boolean fullSchedule;
@@ -49,25 +50,46 @@
@Override
@SuppressWarnings("try")
- protected void run(StructuredGraph graph, PhaseContext context) {
- EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener().exclude(NODE_ADDED);
+ protected void run(StructuredGraph graph, CoreProviders context) {
+ final int maxIterations = GraalOptions.ConditionalEliminationMaxIterations.getValue(graph.getOptions());
+ EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener();
int count = 0;
+
while (true) {
+ count++;
try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
new ConditionalEliminationPhase(fullSchedule).apply(graph, context);
}
if (listener.getNodes().isEmpty()) {
break;
}
- for (Node node : graph.getNodes()) {
- if (node instanceof Simplifiable) {
- listener.getNodes().add(node);
- }
- }
+
canonicalizer.applyIncremental(graph, context, listener.getNodes());
listener.getNodes().clear();
- if (++count > MAX_ITERATIONS) {
- throw new RetryableBailoutException("Number of iterations in ConditionalEliminationPhase phase exceeds %d", MAX_ITERATIONS);
+
+ if (count >= maxIterations) {
+ if (DEBUG_PHASE) {
+ if (count >= DEBUG_MAX_ITERATIONS - 5) {
+ TTY.println();
+ TTY.println("------------------------------------");
+ TTY.println("Iteration " + count);
+ TTY.println("Conditional elimination changed nodes: ");
+ for (Node n : listener.getNodes()) {
+ TTY.println(n.toString());
+ for (Node input : n.inputs()) {
+ TTY.println(" input: " + input);
+ }
+ }
+ TTY.println("Canonicalization with node listener: ");
+ try (NodeEventScope debugNes = graph.trackNodeEvents(new TracingNodeEventListener())) {
+ canonicalizer.applyIncremental(graph, context, listener.getNodes());
+ }
+ }
+ if (count >= DEBUG_MAX_ITERATIONS) {
+ throw new PermanentBailoutException("Number of iterations in ConditionalEliminationPhase phase exceeds %d", DEBUG_MAX_ITERATIONS);
+ }
+ }
+ break;
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -79,7 +79,6 @@
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -92,7 +91,7 @@
/**
* Processes all {@link Lowerable} nodes to do their lowering.
*/
-public class LoweringPhase extends BasePhase<PhaseContext> {
+public class LoweringPhase extends BasePhase<CoreProviders> {
@NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
static final class DummyGuardHandle extends ValueNode implements GuardedNode {
@@ -128,12 +127,12 @@
final class LoweringToolImpl implements LoweringTool {
- private final PhaseContext context;
+ private final CoreProviders context;
private final NodeBitMap activeGuards;
private AnchoringNode guardAnchor;
private FixedWithNextNode lastFixedNode;
- LoweringToolImpl(PhaseContext context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode) {
+ LoweringToolImpl(CoreProviders context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode) {
this.context = context;
this.guardAnchor = guardAnchor;
this.activeGuards = activeGuards;
@@ -252,7 +251,7 @@
* @param graph a graph that was just {@linkplain #lower lowered}
* @throws AssertionError if the check fails
*/
- private boolean checkPostLowering(StructuredGraph graph, PhaseContext context) {
+ private boolean checkPostLowering(StructuredGraph graph, CoreProviders context) {
Mark expectedMark = graph.getMark();
lower(graph, context, LoweringMode.VERIFY_LOWERING);
Mark mark = graph.getMark();
@@ -261,13 +260,13 @@
}
@Override
- protected void run(final StructuredGraph graph, PhaseContext context) {
+ protected void run(final StructuredGraph graph, CoreProviders context) {
lower(graph, context, LoweringMode.LOWERING);
assert checkPostLowering(graph, context);
}
- private void lower(StructuredGraph graph, PhaseContext context, LoweringMode mode) {
- IncrementalCanonicalizerPhase<PhaseContext> incrementalCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer);
+ private void lower(StructuredGraph graph, CoreProviders context, LoweringMode mode) {
+ IncrementalCanonicalizerPhase<CoreProviders> incrementalCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer);
incrementalCanonicalizer.appendPhase(new Round(context, mode, graph.getOptions()));
incrementalCanonicalizer.apply(graph, context);
assert graph.verify();
@@ -351,12 +350,12 @@
private final class Round extends Phase {
- private final PhaseContext context;
+ private final CoreProviders context;
private final LoweringMode mode;
private ScheduleResult schedule;
private final SchedulePhase schedulePhase;
- private Round(PhaseContext context, LoweringMode mode, OptionValues options) {
+ private Round(CoreProviders context, LoweringMode mode, OptionValues options) {
this.context = context;
this.mode = mode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NodeCounterPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NodeCounterPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,13 +27,13 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
-public class NodeCounterPhase extends BasePhase<PhaseContext> {
+public class NodeCounterPhase extends BasePhase<CoreProviders> {
private Stage stage;
@@ -55,7 +55,7 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
for (Node node : graph.getNodes()) {
String nodeName = node.getNodeClass().getClazz().getSimpleName();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,18 +35,18 @@
import org.graalvm.compiler.nodes.ControlSplitNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
/**
* This phase will make sure that the branch leading towards this deopt has 0.0 probability.
*
*/
-public class PropagateDeoptimizeProbabilityPhase extends BasePhase<PhaseContext> {
+public class PropagateDeoptimizeProbabilityPhase extends BasePhase<CoreProviders> {
@Override
@SuppressWarnings("try")
- protected void run(final StructuredGraph graph, PhaseContext context) {
+ protected void run(final StructuredGraph graph, CoreProviders context) {
assert !graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies";
if (graph.hasNode(AbstractDeoptimizeNode.TYPE)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/UseTrappingNullChecksPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -41,6 +41,7 @@
import org.graalvm.compiler.nodes.DeoptimizeNode;
import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
import org.graalvm.compiler.nodes.DynamicDeoptimizeNode;
+import org.graalvm.compiler.nodes.EndNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.IfNode;
import org.graalvm.compiler.nodes.LogicNode;
@@ -115,6 +116,7 @@
reasons = reasonPhi.values().snapshot();
expectedPhis++;
} else if (!reason.isConstant()) {
+ merge.getDebug().log("Non constant reason %s", merge);
return;
}
@@ -135,29 +137,41 @@
}
int index = 0;
- for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) {
+ List<EndNode> predecessors = merge.cfgPredecessors().snapshot();
+ for (AbstractEndNode end : predecessors) {
+ Node endPredecesssor = end.predecessor();
ValueNode thisReason = reasons != null ? reasons.get(index) : reason;
ValueNode thisSpeculation = speculations != null ? speculations.get(index) : speculation;
+ if (!merge.isAlive()) {
+ // When evacuating a merge the last successor simplfies the merge away so it
+ // must be handled specially.
+ assert predecessors.get(predecessors.size() - 1) == end : "must be last end";
+ endPredecesssor = deopt.predecessor();
+ thisSpeculation = deopt.getSpeculation();
+ thisReason = deopt.getActionAndReason();
+ }
+
index++;
if (!thisReason.isConstant() || !thisSpeculation.isConstant()) {
- continue;
- }
- Speculation speculationConstant = metaAccessProvider.decodeSpeculation(thisSpeculation.asJavaConstant(), deopt.graph().getSpeculationLog());
- if (!speculationConstant.equals(SpeculationLog.NO_SPECULATION)) {
+ end.getDebug().log("Non constant deopt %s", end);
continue;
}
DeoptimizationReason deoptimizationReason = metaAccessProvider.decodeDeoptReason(thisReason.asJavaConstant());
- tryUseTrappingNullCheck(deopt, end.predecessor(), deoptimizationReason, SpeculationLog.NO_SPECULATION, implicitNullCheckLimit);
+ Speculation speculationConstant = metaAccessProvider.decodeSpeculation(thisSpeculation.asJavaConstant(), deopt.graph().getSpeculationLog());
+ tryUseTrappingNullCheck(deopt, endPredecesssor, deoptimizationReason, speculationConstant, implicitNullCheckLimit);
}
}
}
private static void tryUseTrappingNullCheck(AbstractDeoptimizeNode deopt, Node predecessor, DeoptimizationReason deoptimizationReason, Speculation speculation, long implicitNullCheckLimit) {
+ assert predecessor != null;
if (deoptimizationReason != DeoptimizationReason.NullCheckException && deoptimizationReason != DeoptimizationReason.UnreachedCode) {
+ deopt.getDebug().log(DebugContext.INFO_LEVEL, "Not a null check or unreached %s", predecessor);
return;
}
assert speculation != null;
if (!speculation.equals(SpeculationLog.NO_SPECULATION)) {
+ deopt.getDebug().log(DebugContext.INFO_LEVEL, "Has a speculation %s", predecessor);
return;
}
if (predecessor instanceof AbstractMergeNode) {
@@ -169,6 +183,8 @@
}
} else if (predecessor instanceof AbstractBeginNode) {
checkPredecessor(deopt, predecessor, deoptimizationReason, implicitNullCheckLimit);
+ } else {
+ deopt.getDebug().log(DebugContext.INFO_LEVEL, "Not a Begin or Merge %s", predecessor);
}
}
@@ -233,6 +249,7 @@
deopt.graph().removeSplit(ifNode, nonTrappingContinuation);
trappingNullCheck = fixedAccessNode;
counterTrappingNullCheckExistingRead.increment(debug);
+ deopt.getDebug().log("Added implicit null check to %s", fixedAccessNode);
}
}
}
@@ -242,6 +259,7 @@
// Need to add a null check node.
trappingNullCheck = deopt.graph().add(new NullCheckNode(value));
deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
+ deopt.getDebug().log("Inserted NullCheckNode %s", trappingNullCheck);
}
trappingNullCheck.setStateBefore(deopt.stateBefore());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.phases.common;
+
+import org.graalvm.compiler.debug.DebugCloseable;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.gc.BarrierSet;
+import org.graalvm.compiler.nodes.memory.FixedAccessNode;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.tiers.MidTierContext;
+
+public class WriteBarrierAdditionPhase extends BasePhase<MidTierContext> {
+ @SuppressWarnings("try")
+ @Override
+ protected void run(StructuredGraph graph, MidTierContext context) {
+ BarrierSet barrierSet = context.getGC().getBarrierSet();
+ for (FixedAccessNode n : graph.getNodes().filter(FixedAccessNode.class)) {
+ try (DebugCloseable scope = n.graph().withNodeSourcePosition(n)) {
+ barrierSet.addBarriers(n);
+ }
+ }
+ }
+
+ @Override
+ public boolean checkContract() {
+ return false;
+ }
+}
+
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Fri Jun 28 14:36:42 2019 +0530
@@ -381,7 +381,7 @@
throw new IllegalStateException("Inlined graph is in invalid state: " + inlineGraph);
}
for (Node node : inlineGraph.getNodes()) {
- if (node == entryPointNode || (node == entryPointNode.stateAfter() && node.usages().count() == 1) || node instanceof ParameterNode) {
+ if (node == entryPointNode || (node == entryPointNode.stateAfter() && node.hasExactlyOneUsage()) || node instanceof ParameterNode) {
// Do nothing.
} else {
nodes.add(node);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -145,7 +145,11 @@
OptionValues options = rootGraph.getOptions();
if (method == null) {
return "the method is not resolved";
- } else if (method.isNative() && (!Intrinsify.getValue(options) || !context.getReplacements().hasSubstitution(method, invokeBci))) {
+ } else if (method.isNative() && !(Intrinsify.getValue(options) &&
+ context.getReplacements().getSubstitution(method, invokeBci, rootGraph.trackNodeSourcePosition(), null, options) != null)) {
+ // We have conditional intrinsic, e.g., String.intern, which may not have inlineable
+ // graph depending on the context. The getSubstitution test ensures the inlineable
+ // graph is present.
return "it is a non-intrinsic native method";
} else if (method.isAbstract()) {
return "it is an abstract method";
@@ -155,8 +159,6 @@
return "it is marked non-inlinable";
} else if (countRecursiveInlining(method) > MaximumRecursiveInlining.getValue(options)) {
return "it exceeds the maximum recursive inlining depth";
- } else if (!method.hasBytecodes()) {
- return "it has no bytecodes to inline";
} else {
if (new OptimisticOptimizations(rootGraph.getProfilingInfo(method), options).lessOptimisticThan(context.getOptimisticOptimizations())) {
return "the callee uses less optimistic optimizations than caller";
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/EconomicSetNodeEventListener.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/EconomicSetNodeEventListener.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,6 +33,7 @@
import org.graalvm.compiler.graph.Graph.NodeEventListener;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.Node.IndirectCanonicalization;
+import org.graalvm.compiler.nodes.AbstractBeginNode;
/**
* A simple {@link NodeEventListener} implementation that accumulates event nodes in a
@@ -48,7 +49,7 @@
*/
public EconomicSetNodeEventListener() {
this.nodes = EconomicSet.create(Equivalence.IDENTITY);
- this.filter = EnumSet.allOf(NodeEvent.class);
+ this.filter = EnumSet.of(NodeEvent.INPUT_CHANGED, NodeEvent.NODE_ADDED, NodeEvent.ZERO_USAGES);
}
/**
@@ -71,12 +72,23 @@
@Override
public void changed(NodeEvent e, Node node) {
if (filter.contains(e)) {
- nodes.add(node);
+ add(node);
if (node instanceof IndirectCanonicalization) {
for (Node usage : node.usages()) {
- nodes.add(usage);
+ add(usage);
}
}
+
+ if (node instanceof AbstractBeginNode) {
+ AbstractBeginNode abstractBeginNode = (AbstractBeginNode) node;
+ add(abstractBeginNode.predecessor());
+ }
+ }
+ }
+
+ private void add(Node n) {
+ if (n != null) {
+ nodes.add(n);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/TracingNodeEventListener.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.phases.common.util;
+
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.graph.Graph.NodeEvent;
+import org.graalvm.compiler.graph.Graph.NodeEventListener;
+import org.graalvm.compiler.graph.Node;
+
+/**
+ * A simple {@link NodeEventListener} implementation that traces events to TTY for debugging
+ * purposes.
+ */
+public class TracingNodeEventListener extends NodeEventListener {
+
+ @Override
+ public void changed(NodeEvent e, Node node) {
+ TTY.println(e.toString() + ": " + node);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java Fri Jun 28 14:36:42 2019 +0530
@@ -195,10 +195,7 @@
return true;
} else if (phase instanceof PhaseSuite) {
PhaseSuite<C> innerSuite = (PhaseSuite<C>) phase;
- if (innerSuite.removePhase(phaseClass)) {
- if (innerSuite.phases.isEmpty()) {
- it.set(newPhase);
- }
+ if (innerSuite.replacePhase(phaseClass, newPhase)) {
return true;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -94,7 +94,7 @@
EARLIEST,
LATEST,
LATEST_OUT_OF_LOOPS,
- FINAL_SCHEDULE;
+ LATEST_OUT_OF_LOOPS_IMPLICIT_NULL_CHECKS;
public boolean isEarliest() {
return this == EARLIEST || this == EARLIEST_WITH_GUARD_ORDER;
@@ -103,6 +103,14 @@
public boolean isLatest() {
return !isEarliest();
}
+
+ public boolean scheduleOutOfLoops() {
+ return this == LATEST_OUT_OF_LOOPS || this == LATEST_OUT_OF_LOOPS_IMPLICIT_NULL_CHECKS;
+ }
+
+ public boolean considerImplicitNullChecks() {
+ return this == LATEST_OUT_OF_LOOPS_IMPLICIT_NULL_CHECKS;
+ }
}
private final SchedulingStrategy selectedStrategy;
@@ -228,8 +236,14 @@
} else {
Block latestBlock = null;
+ if (currentBlock.getFirstDominated() == null && !(currentNode instanceof VirtualState)) {
+ // This block doesn't dominate any other blocks =>
+ // node must be scheduled in earliest block.
+ latestBlock = currentBlock;
+ }
+
LocationIdentity constrainingLocation = null;
- if (currentNode instanceof FloatingReadNode) {
+ if (latestBlock == null && currentNode instanceof FloatingReadNode) {
// We are scheduling a floating read node => check memory
// anti-dependencies.
FloatingReadNode floatingReadNode = (FloatingReadNode) currentNode;
@@ -544,7 +558,7 @@
assert latestBlock != null : currentNode;
- if (strategy == SchedulingStrategy.FINAL_SCHEDULE || strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS) {
+ if (strategy.scheduleOutOfLoops()) {
Block currentBlock = latestBlock;
while (currentBlock.getLoopDepth() > earliestBlock.getLoopDepth() && currentBlock != earliestBlock.getDominator()) {
Block previousCurrentBlock = currentBlock;
@@ -564,27 +578,25 @@
}
}
- if (latestBlock != earliestBlock && currentNode instanceof FloatingReadNode) {
-
- FloatingReadNode floatingReadNode = (FloatingReadNode) currentNode;
- if (isImplicitNullOpportunity(floatingReadNode, earliestBlock) &&
- earliestBlock.getRelativeFrequency() < latestBlock.getRelativeFrequency() * IMPLICIT_NULL_CHECK_OPPORTUNITY_PROBABILITY_FACTOR) {
- latestBlock = earliestBlock;
- }
+ if (latestBlock != earliestBlock && strategy.considerImplicitNullChecks() && isImplicitNullOpportunity(currentNode, earliestBlock) &&
+ earliestBlock.getRelativeFrequency() < latestBlock.getRelativeFrequency() * IMPLICIT_NULL_CHECK_OPPORTUNITY_PROBABILITY_FACTOR) {
+ latestBlock = earliestBlock;
}
selectLatestBlock(currentNode, earliestBlock, latestBlock, currentNodeMap, watchListMap, constrainingLocation, latestBlockToNodesMap);
}
- private static boolean isImplicitNullOpportunity(FloatingReadNode floatingReadNode, Block block) {
-
- Node pred = block.getBeginNode().predecessor();
- if (pred instanceof IfNode) {
- IfNode ifNode = (IfNode) pred;
- if (ifNode.condition() instanceof IsNullNode) {
- IsNullNode isNullNode = (IsNullNode) ifNode.condition();
- if (getUnproxifiedUncompressed(floatingReadNode.getAddress().getBase()) == getUnproxifiedUncompressed(isNullNode.getValue())) {
- return true;
+ protected static boolean isImplicitNullOpportunity(Node currentNode, Block block) {
+ if (currentNode instanceof FloatingReadNode) {
+ FloatingReadNode floatingReadNode = (FloatingReadNode) currentNode;
+ Node pred = block.getBeginNode().predecessor();
+ if (pred instanceof IfNode) {
+ IfNode ifNode = (IfNode) pred;
+ if (ifNode.condition() instanceof IsNullNode && ifNode.getTrueSuccessorProbability() == 0.0) {
+ IsNullNode isNullNode = (IsNullNode) ifNode.condition();
+ if (getUnproxifiedUncompressed(floatingReadNode.getAddress().getBase()) == getUnproxifiedUncompressed(isNullNode.getValue())) {
+ return true;
+ }
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/HighTierContext.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/HighTierContext.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,11 +24,12 @@
package org.graalvm.compiler.phases.tiers;
+import org.graalvm.compiler.nodes.spi.CoreProvidersDelegate;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.util.Providers;
-public class HighTierContext extends PhaseContext {
+public class HighTierContext extends CoreProvidersDelegate {
private final PhaseSuite<HighTierContext> graphBuilderSuite;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/LowTierContext.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/LowTierContext.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,11 +24,12 @@
package org.graalvm.compiler.phases.tiers;
+import org.graalvm.compiler.nodes.spi.CoreProvidersDelegate;
import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.code.TargetDescription;
-public class LowTierContext extends PhaseContext {
+public class LowTierContext extends CoreProvidersDelegate {
private final TargetProvider target;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/MidTierContext.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/MidTierContext.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,13 +24,14 @@
package org.graalvm.compiler.phases.tiers;
+import org.graalvm.compiler.nodes.spi.CoreProvidersDelegate;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.ProfilingInfo;
-public class MidTierContext extends PhaseContext {
+public class MidTierContext extends CoreProvidersDelegate {
private final TargetProvider target;
private final OptimisticOptimizations optimisticOpts;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/PhaseContext.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.phases.tiers;
-
-import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
-import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
-import org.graalvm.compiler.nodes.spi.CoreProviders;
-import org.graalvm.compiler.nodes.spi.LoweringProvider;
-import org.graalvm.compiler.nodes.spi.Replacements;
-import org.graalvm.compiler.nodes.spi.StampProvider;
-
-import jdk.vm.ci.meta.ConstantReflectionProvider;
-import jdk.vm.ci.meta.MetaAccessProvider;
-
-public class PhaseContext implements CoreProviders {
-
- private final CoreProviders providers;
-
- public PhaseContext(CoreProviders providers) {
- this.providers = providers;
- }
-
- @Override
- public MetaAccessProvider getMetaAccess() {
- return providers.getMetaAccess();
- }
-
- @Override
- public ConstantReflectionProvider getConstantReflection() {
- return providers.getConstantReflection();
- }
-
- @Override
- public ConstantFieldProvider getConstantFieldProvider() {
- return providers.getConstantFieldProvider();
- }
-
- @Override
- public LoweringProvider getLowerer() {
- return providers.getLowerer();
- }
-
- @Override
- public Replacements getReplacements() {
- return providers.getReplacements();
- }
-
- @Override
- public StampProvider getStampProvider() {
- return providers.getStampProvider();
- }
-
- @Override
- public ForeignCallsProvider getForeignCalls() {
- return providers.getForeignCalls();
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,11 +27,12 @@
import org.graalvm.compiler.core.common.spi.CodeGenProviders;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.CoreProvidersImpl;
+import org.graalvm.compiler.nodes.spi.GCProvider;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.nodes.spi.StampProvider;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -45,19 +46,19 @@
private final CodeCacheProvider codeCache;
public Providers(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider,
- ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider) {
- super(metaAccess, constantReflection, constantFieldProvider, lowerer, replacements, stampProvider, foreignCalls);
+ ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, GCProvider gc) {
+ super(metaAccess, constantReflection, constantFieldProvider, lowerer, replacements, stampProvider, foreignCalls, gc);
this.codeCache = codeCache;
}
public Providers(Providers copyFrom) {
this(copyFrom.getMetaAccess(), copyFrom.getCodeCache(), copyFrom.getConstantReflection(), copyFrom.getConstantFieldProvider(), copyFrom.getForeignCalls(), copyFrom.getLowerer(),
- copyFrom.getReplacements(), copyFrom.getStampProvider());
+ copyFrom.getReplacements(), copyFrom.getStampProvider(), copyFrom.getGC());
}
- public Providers(PhaseContext copyFrom) {
+ public Providers(CoreProviders copyFrom) {
this(copyFrom.getMetaAccess(), null, copyFrom.getConstantReflection(), copyFrom.getConstantFieldProvider(), null, copyFrom.getLowerer(), copyFrom.getReplacements(),
- copyFrom.getStampProvider());
+ copyFrom.getStampProvider(), copyFrom.getGC());
}
@Override
@@ -67,41 +68,46 @@
public Providers copyWith(MetaAccessProvider substitution) {
assert this.getClass() == Providers.class : "must override";
- return new Providers(substitution, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
+ return new Providers(substitution, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, gc);
}
public Providers copyWith(CodeCacheProvider substitution) {
assert this.getClass() == Providers.class : "must override";
- return new Providers(metaAccess, substitution, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
+ return new Providers(metaAccess, substitution, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, gc);
}
public Providers copyWith(ConstantReflectionProvider substitution) {
assert this.getClass() == Providers.class : "must override";
- return new Providers(metaAccess, codeCache, substitution, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider);
+ return new Providers(metaAccess, codeCache, substitution, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, gc);
}
public Providers copyWith(ConstantFieldProvider substitution) {
assert this.getClass() == Providers.class : "must override";
- return new Providers(metaAccess, codeCache, constantReflection, substitution, foreignCalls, lowerer, replacements, stampProvider);
+ return new Providers(metaAccess, codeCache, constantReflection, substitution, foreignCalls, lowerer, replacements, stampProvider, gc);
}
public Providers copyWith(ForeignCallsProvider substitution) {
assert this.getClass() == Providers.class : "must override";
- return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, substitution, lowerer, replacements, stampProvider);
+ return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, substitution, lowerer, replacements, stampProvider, gc);
}
public Providers copyWith(LoweringProvider substitution) {
assert this.getClass() == Providers.class : "must override";
- return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, substitution, replacements, stampProvider);
+ return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, substitution, replacements, stampProvider, gc);
}
public Providers copyWith(Replacements substitution) {
assert this.getClass() == Providers.class : "must override in " + getClass();
- return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, substitution, stampProvider);
+ return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, substitution, stampProvider, gc);
}
public Providers copyWith(StampProvider substitution) {
assert this.getClass() == Providers.class : "must override";
- return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, substitution);
+ return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, substitution, gc);
+ }
+
+ public Providers copyWith(GCProvider substitution) {
+ assert this.getClass() == Providers.class : "must override";
+ return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, substitution);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,9 +31,6 @@
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool.RoundingMode;
@@ -51,6 +48,7 @@
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
@@ -166,7 +164,7 @@
}
private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
- if (JAVA_SPECIFICATION_VERSION >= 9) {
+ if (JavaVersionUtil.JAVA_SPEC >= 9) {
Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AArch64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
@@ -175,7 +173,7 @@
}
private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
- if (JAVA_SPECIFICATION_VERSION >= 9) {
+ if (JavaVersionUtil.JAVA_SPEC >= 9) {
Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
r.setAllowOverwrite(true);
r.registerMethodSubstitution(AArch64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
@@ -186,10 +184,10 @@
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
registerUnsafePlugins(new Registration(plugins, Unsafe.class),
new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}, "Object");
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", replacementsBytecodeProvider),
new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object},
- Java11OrEarlier ? "Object" : "Reference");
+ JavaVersionUtil.JAVA_SPEC <= 11 ? "Object" : "Reference");
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOf.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOf.java Fri Jun 28 14:36:42 2019 +0530
@@ -25,101 +25,100 @@
package org.graalvm.compiler.replacements.amd64;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
-import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
-import org.graalvm.compiler.nodes.extended.ForeignCallNode;
-import jdk.internal.vm.compiler.word.Pointer;
-
-import static org.graalvm.compiler.graph.Node.NodeIntrinsic;
public class AMD64ArrayIndexOf {
public static final ForeignCallDescriptor STUB_INDEX_OF_TWO_CONSECUTIVE_BYTES = new ForeignCallDescriptor(
- "indexOfTwoConsecutiveBytes", int.class, Pointer.class, int.class, int.class);
+ "indexOfTwoConsecutiveBytes", int.class, byte[].class, int.class, int.class, int.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS = new ForeignCallDescriptor(
- "indexOfTwoConsecutiveChars", int.class, Pointer.class, int.class, int.class);
+ "indexOfTwoConsecutiveChars", int.class, char[].class, int.class, int.class, int.class);
+ public static final ForeignCallDescriptor STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS_COMPACT = new ForeignCallDescriptor(
+ "indexOfTwoConsecutiveCharsCompact", int.class, byte[].class, int.class, int.class, int.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_1_BYTE = new ForeignCallDescriptor(
- "indexOf1Byte", int.class, Pointer.class, int.class, byte.class);
+ "indexOf1Byte", int.class, byte[].class, int.class, int.class, byte.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_2_BYTES = new ForeignCallDescriptor(
- "indexOf2Bytes", int.class, Pointer.class, int.class, byte.class, byte.class);
+ "indexOf2Bytes", int.class, byte[].class, int.class, int.class, byte.class, byte.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_3_BYTES = new ForeignCallDescriptor(
- "indexOf3Bytes", int.class, Pointer.class, int.class, byte.class, byte.class, byte.class);
+ "indexOf3Bytes", int.class, byte[].class, int.class, int.class, byte.class, byte.class, byte.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_4_BYTES = new ForeignCallDescriptor(
- "indexOf4Bytes", int.class, Pointer.class, int.class, byte.class, byte.class, byte.class, byte.class);
+ "indexOf4Bytes", int.class, byte[].class, int.class, int.class, byte.class, byte.class, byte.class, byte.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_1_CHAR = new ForeignCallDescriptor(
- "indexOf1Char", int.class, Pointer.class, int.class, char.class);
+ "indexOf1Char", int.class, char[].class, int.class, int.class, char.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_2_CHARS = new ForeignCallDescriptor(
- "indexOf2Chars", int.class, Pointer.class, int.class, char.class, char.class);
+ "indexOf2Chars", int.class, char[].class, int.class, int.class, char.class, char.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_3_CHARS = new ForeignCallDescriptor(
- "indexOf3Chars", int.class, Pointer.class, int.class, char.class, char.class, char.class);
+ "indexOf3Chars", int.class, char[].class, int.class, int.class, char.class, char.class, char.class);
public static final ForeignCallDescriptor STUB_INDEX_OF_4_CHARS = new ForeignCallDescriptor(
- "indexOf4Chars", int.class, Pointer.class, int.class, char.class, char.class, char.class, char.class);
+ "indexOf4Chars", int.class, char[].class, int.class, int.class, char.class, char.class, char.class, char.class);
+ public static final ForeignCallDescriptor STUB_INDEX_OF_1_CHAR_COMPACT = new ForeignCallDescriptor(
+ "indexOf1CharCompact", int.class, byte[].class, int.class, int.class, char.class);
+ public static final ForeignCallDescriptor STUB_INDEX_OF_2_CHARS_COMPACT = new ForeignCallDescriptor(
+ "indexOf2CharsCompact", int.class, byte[].class, int.class, int.class, char.class, char.class);
+ public static final ForeignCallDescriptor STUB_INDEX_OF_3_CHARS_COMPACT = new ForeignCallDescriptor(
+ "indexOf3CharsCompact", int.class, byte[].class, int.class, int.class, char.class, char.class, char.class);
+ public static final ForeignCallDescriptor STUB_INDEX_OF_4_CHARS_COMPACT = new ForeignCallDescriptor(
+ "indexOf4CharsCompact", int.class, byte[].class, int.class, int.class, char.class, char.class, char.class, char.class);
- public static int indexOfTwoConsecutiveBytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2) {
+ public static int indexOfTwoConsecutiveBytes(byte[] array, int arrayLength, int fromIndex, byte b1, byte b2) {
int searchValue = (Byte.toUnsignedInt(b2) << Byte.SIZE) | Byte.toUnsignedInt(b1);
- return callInt(STUB_INDEX_OF_TWO_CONSECUTIVE_BYTES, arrayPointer, arrayLength, searchValue);
+ return AMD64ArrayIndexOfDispatchNode.indexOf2ConsecutiveBytes(STUB_INDEX_OF_TWO_CONSECUTIVE_BYTES, array, arrayLength, fromIndex, searchValue);
}
- public static int indexOfTwoConsecutiveChars(Pointer arrayPointer, int arrayLength, char c1, char c2) {
+ public static int indexOfTwoConsecutiveChars(char[] array, int arrayLength, int fromIndex, char c1, char c2) {
int searchValue = (c2 << Character.SIZE) | c1;
- return callInt(STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS, arrayPointer, arrayLength, searchValue);
+ return AMD64ArrayIndexOfDispatchNode.indexOf2ConsecutiveChars(STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS, array, arrayLength, fromIndex, searchValue);
}
- public static int indexOf1Byte(Pointer arrayPointer, int arrayLength, byte b) {
- return callByte1(STUB_INDEX_OF_1_BYTE, arrayPointer, arrayLength, b);
- }
-
- public static int indexOf2Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2) {
- return callByte2(STUB_INDEX_OF_2_BYTES, arrayPointer, arrayLength, b1, b2);
- }
-
- public static int indexOf3Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2, byte b3) {
- return callByte3(STUB_INDEX_OF_3_BYTES, arrayPointer, arrayLength, b1, b2, b3);
+ public static int indexOfTwoConsecutiveChars(byte[] array, int arrayLength, int fromIndex, char c1, char c2) {
+ int searchValue = (c2 << Character.SIZE) | c1;
+ return AMD64ArrayIndexOfDispatchNode.indexOf2ConsecutiveChars(STUB_INDEX_OF_TWO_CONSECUTIVE_CHARS_COMPACT, array, arrayLength, fromIndex, searchValue);
}
- public static int indexOf4Bytes(Pointer arrayPointer, int arrayLength, byte b1, byte b2, byte b3, byte b4) {
- return callByte4(STUB_INDEX_OF_4_BYTES, arrayPointer, arrayLength, b1, b2, b3, b4);
+ public static int indexOf1Byte(byte[] array, int arrayLength, int fromIndex, byte b) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_1_BYTE, array, arrayLength, fromIndex, b);
}
- public static int indexOf1Char(Pointer arrayPointer, int arrayLength, char c) {
- return callChar1(STUB_INDEX_OF_1_CHAR, arrayPointer, arrayLength, c);
+ public static int indexOf2Bytes(byte[] array, int arrayLength, int fromIndex, byte b1, byte b2) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_2_BYTES, array, arrayLength, fromIndex, b1, b2);
}
- public static int indexOf2Chars(Pointer arrayPointer, int arrayLength, char c1, char c2) {
- return callChar2(STUB_INDEX_OF_2_CHARS, arrayPointer, arrayLength, c1, c2);
+ public static int indexOf3Bytes(byte[] array, int arrayLength, int fromIndex, byte b1, byte b2, byte b3) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_3_BYTES, array, arrayLength, fromIndex, b1, b2, b3);
}
- public static int indexOf3Chars(Pointer arrayPointer, int arrayLength, char c1, char c2, char c3) {
- return callChar3(STUB_INDEX_OF_3_CHARS, arrayPointer, arrayLength, c1, c2, c3);
+ public static int indexOf4Bytes(byte[] array, int arrayLength, int fromIndex, byte b1, byte b2, byte b3, byte b4) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_4_BYTES, array, arrayLength, fromIndex, b1, b2, b3, b4);
}
- public static int indexOf4Chars(Pointer arrayPointer, int arrayLength, char c1, char c2, char c3, char c4) {
- return callChar4(STUB_INDEX_OF_4_CHARS, arrayPointer, arrayLength, c1, c2, c3, c4);
+ public static int indexOf1Char(char[] array, int arrayLength, int fromIndex, char c) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_1_CHAR, array, arrayLength, fromIndex, c);
+ }
+
+ public static int indexOf2Chars(char[] array, int arrayLength, int fromIndex, char c1, char c2) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_2_CHARS, array, arrayLength, fromIndex, c1, c2);
}
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callInt(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, int v1);
-
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callByte1(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, byte v1);
+ public static int indexOf3Chars(char[] array, int arrayLength, int fromIndex, char c1, char c2, char c3) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_3_CHARS, array, arrayLength, fromIndex, c1, c2, c3);
+ }
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callByte2(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, byte v1, byte v2);
+ public static int indexOf4Chars(char[] array, int arrayLength, int fromIndex, char c1, char c2, char c3, char c4) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_4_CHARS, array, arrayLength, fromIndex, c1, c2, c3, c4);
+ }
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callByte3(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, byte v1, byte v2, byte v3);
+ public static int indexOf1Char(byte[] array, int arrayLength, int fromIndex, char c) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_1_CHAR_COMPACT, array, arrayLength, fromIndex, c);
+ }
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callByte4(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, byte v1, byte v2, byte v3, byte v4);
-
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callChar1(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, char v1);
+ public static int indexOf2Chars(byte[] array, int arrayLength, int fromIndex, char c1, char c2) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_2_CHARS_COMPACT, array, arrayLength, fromIndex, c1, c2);
+ }
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callChar2(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, char v1, char v2);
+ public static int indexOf3Chars(byte[] array, int arrayLength, int fromIndex, char c1, char c2, char c3) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_3_CHARS_COMPACT, array, arrayLength, fromIndex, c1, c2, c3);
+ }
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callChar3(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, char v1, char v2, char v3);
-
- @NodeIntrinsic(value = ForeignCallNode.class)
- private static native int callChar4(@ConstantNodeParameter ForeignCallDescriptor descriptor, Pointer arrayPointer, int arrayLength, char v1, char v2, char v3, char v4);
+ public static int indexOf4Chars(byte[] array, int arrayLength, int fromIndex, char c1, char c2, char c3, char c4) {
+ return AMD64ArrayIndexOfDispatchNode.indexOf(STUB_INDEX_OF_4_CHARS_COMPACT, array, arrayLength, fromIndex, c1, c2, c3, c4);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOfDispatchNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.amd64;
+
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_512;
+
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.NodeInputList;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeCycles;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.DeoptimizingNode;
+import org.graalvm.compiler.nodes.FixedWithNextNode;
+import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.NamedLocationIdentity;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.ValueNodeUtil;
+import org.graalvm.compiler.nodes.memory.MemoryAccess;
+import org.graalvm.compiler.nodes.memory.MemoryNode;
+import org.graalvm.compiler.nodes.spi.Lowerable;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+
+import jdk.vm.ci.meta.JavaKind;
+
+/**
+ * This node is a placeholder for all variants of intrinsified indexof-operations. It may be lowered
+ * to a {@link AMD64ArrayIndexOfNode} or a specialized snippet.
+ */
+@NodeInfo(size = SIZE_512, cycles = NodeCycles.CYCLES_UNKNOWN)
+public class AMD64ArrayIndexOfDispatchNode extends FixedWithNextNode implements Lowerable, MemoryAccess, DeoptimizingNode.DeoptBefore {
+
+ public static final NodeClass<AMD64ArrayIndexOfDispatchNode> TYPE = NodeClass.create(AMD64ArrayIndexOfDispatchNode.class);
+
+ private final ForeignCallDescriptor stubCallDescriptor;
+ private final JavaKind arrayKind;
+ private final JavaKind valueKind;
+ private final boolean findTwoConsecutive;
+
+ @Input private ValueNode arrayPointer;
+ @Input private ValueNode arrayLength;
+ @Input private ValueNode fromIndex;
+ @Input private NodeInputList<ValueNode> searchValues;
+
+ @OptionalInput(InputType.Memory) private MemoryNode lastLocationAccess;
+ @OptionalInput(InputType.State) protected FrameState stateBefore;
+
+ public AMD64ArrayIndexOfDispatchNode(@ConstantNodeParameter ForeignCallDescriptor stubCallDescriptor, @ConstantNodeParameter JavaKind arrayKind, @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive, ValueNode arrayPointer, ValueNode arrayLength, ValueNode fromIndex, ValueNode... searchValues) {
+ super(TYPE, StampFactory.forKind(JavaKind.Int));
+ this.stubCallDescriptor = stubCallDescriptor;
+ this.arrayKind = arrayKind;
+ this.valueKind = valueKind;
+ this.findTwoConsecutive = findTwoConsecutive;
+ this.arrayPointer = arrayPointer;
+ this.arrayLength = arrayLength;
+ this.fromIndex = fromIndex;
+ this.searchValues = new NodeInputList<>(this, searchValues);
+ }
+
+ public boolean isFindTwoConsecutive() {
+ return findTwoConsecutive;
+ }
+
+ public ValueNode getArrayPointer() {
+ return arrayPointer;
+ }
+
+ public ValueNode getArrayLength() {
+ return arrayLength;
+ }
+
+ public ValueNode getFromIndex() {
+ return fromIndex;
+ }
+
+ public NodeInputList<ValueNode> getSearchValues() {
+ return searchValues;
+ }
+
+ @Override
+ public boolean canDeoptimize() {
+ return true;
+ }
+
+ @Override
+ public void setStateBefore(FrameState f) {
+ updateUsages(stateBefore, f);
+ stateBefore = f;
+ }
+
+ @Override
+ public FrameState stateBefore() {
+ return stateBefore;
+ }
+
+ public ForeignCallDescriptor getStubCallDescriptor() {
+ return stubCallDescriptor;
+ }
+
+ public int getNumberOfValues() {
+ return searchValues.size();
+ }
+
+ public JavaKind getArrayKind() {
+ return arrayKind;
+ }
+
+ public JavaKind getValueKind() {
+ return valueKind;
+ }
+
+ public JavaKind getComparisonKind() {
+ return findTwoConsecutive ? (valueKind == JavaKind.Byte ? JavaKind.Char : JavaKind.Int) : valueKind;
+ }
+
+ public ValueNode[] getStubCallArgs() {
+ ValueNode[] ret = new ValueNode[searchValues.size() + 3];
+ ret[0] = arrayPointer;
+ ret[1] = arrayLength;
+ ret[2] = fromIndex;
+ for (int i = 0; i < searchValues.size(); i++) {
+ ret[3 + i] = searchValues.get(i);
+ }
+ return ret;
+ }
+
+ public AMD64ArrayIndexOfDispatchNode(@ConstantNodeParameter ForeignCallDescriptor stubCallDescriptor, @ConstantNodeParameter JavaKind arrayKind, @ConstantNodeParameter JavaKind valueKind,
+ ValueNode arrayPointer, ValueNode arrayLength, ValueNode fromIndex, ValueNode... searchValues) {
+ this(stubCallDescriptor, arrayKind, valueKind, false, arrayPointer, arrayLength, fromIndex, searchValues);
+ }
+
+ @Override
+ public LocationIdentity getLocationIdentity() {
+ return NamedLocationIdentity.getArrayLocation(arrayKind);
+ }
+
+ @Override
+ public void lower(LoweringTool tool) {
+ tool.getLowerer().lower(this, tool);
+ }
+
+ @Override
+ public MemoryNode getLastLocationAccess() {
+ return lastLocationAccess;
+ }
+
+ @Override
+ public void setLastLocationAccess(MemoryNode lla) {
+ updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(lla));
+ lastLocationAccess = lla;
+ }
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1, byte v2);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3, byte v4);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1, char v2);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1, char v2, char v3);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1, char v2, char v3, char v4);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter ForeignCallDescriptor descriptor,
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, int searchValue);
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, byte v1) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, byte v1, byte v2) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1, v2);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1, v2, v3);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3, byte v4) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1, v2, v3, v4);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, char v1) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, char v1, char v2) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, char v1, char v2, char v3) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, char v1, char v2, char v3, char v4) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3, v4);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, char[] array, int arrayLength, int fromIndex, char v1) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, char[] array, int arrayLength, int fromIndex, char v1, char v2) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, char[] array, int arrayLength, int fromIndex, char v1, char v2, char v3) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3);
+ }
+
+ public static int indexOf(@ConstantNodeParameter ForeignCallDescriptor descriptor, char[] array, int arrayLength, int fromIndex, char v1, char v2, char v3, char v4) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3, v4);
+ }
+
+ public static int indexOf2ConsecutiveBytes(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, int values) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Byte, true, array, arrayLength, fromIndex, values);
+ }
+
+ public static int indexOf2ConsecutiveChars(@ConstantNodeParameter ForeignCallDescriptor descriptor, byte[] array, int arrayLength, int fromIndex, int values) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Byte, JavaKind.Char, true, array, arrayLength, fromIndex, values);
+ }
+
+ public static int indexOf2ConsecutiveChars(@ConstantNodeParameter ForeignCallDescriptor descriptor, char[] array, int arrayLength, int fromIndex, int values) {
+ return optimizedArrayIndexOf(descriptor, JavaKind.Char, JavaKind.Char, true, array, arrayLength, fromIndex, values);
+ }
+}
+
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOfNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOfNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,8 +24,8 @@
package org.graalvm.compiler.replacements.amd64;
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.Value;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_512;
+
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
@@ -41,41 +41,46 @@
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.internal.vm.compiler.word.LocationIdentity;
-import jdk.internal.vm.compiler.word.Pointer;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_512;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
@NodeInfo(size = SIZE_512, cycles = NodeCycles.CYCLES_UNKNOWN)
public class AMD64ArrayIndexOfNode extends FixedWithNextNode implements LIRLowerable, MemoryAccess {
public static final NodeClass<AMD64ArrayIndexOfNode> TYPE = NodeClass.create(AMD64ArrayIndexOfNode.class);
- private final JavaKind kind;
+ private final JavaKind arrayKind;
+ private final JavaKind valueKind;
private final boolean findTwoConsecutive;
@Input private ValueNode arrayPointer;
@Input private ValueNode arrayLength;
+ @Input private ValueNode fromIndex;
@Input private NodeInputList<ValueNode> searchValues;
@OptionalInput(InputType.Memory) private MemoryNode lastLocationAccess;
- public AMD64ArrayIndexOfNode(@ConstantNodeParameter JavaKind kind, @ConstantNodeParameter boolean findTwoConsecutive,
- ValueNode arrayPointer, ValueNode arrayLength, ValueNode... searchValues) {
+ public AMD64ArrayIndexOfNode(@ConstantNodeParameter JavaKind arrayKind, @ConstantNodeParameter JavaKind valueKind, @ConstantNodeParameter boolean findTwoConsecutive,
+ ValueNode arrayPointer, ValueNode arrayLength, ValueNode fromIndex, ValueNode... searchValues) {
super(TYPE, StampFactory.forKind(JavaKind.Int));
- this.kind = kind;
+ this.arrayKind = arrayKind;
+ this.valueKind = valueKind;
this.findTwoConsecutive = findTwoConsecutive;
this.arrayPointer = arrayPointer;
this.arrayLength = arrayLength;
+ this.fromIndex = fromIndex;
this.searchValues = new NodeInputList<>(this, searchValues);
}
- public AMD64ArrayIndexOfNode(@ConstantNodeParameter JavaKind kind, ValueNode arrayPointer, ValueNode arrayLength, ValueNode... searchValues) {
- this(kind, false, arrayPointer, arrayLength, searchValues);
+ public AMD64ArrayIndexOfNode(@ConstantNodeParameter JavaKind arrayKind, @ConstantNodeParameter JavaKind valueKind,
+ ValueNode arrayPointer, ValueNode arrayLength, ValueNode fromIndex, ValueNode... searchValues) {
+ this(arrayKind, valueKind, false, arrayPointer, arrayLength, fromIndex, searchValues);
}
@Override
public LocationIdentity getLocationIdentity() {
- return NamedLocationIdentity.getArrayLocation(kind);
+ return NamedLocationIdentity.getArrayLocation(arrayKind);
}
@Override
@@ -84,7 +89,8 @@
for (int i = 0; i < searchValues.size(); i++) {
searchValueOperands[i] = gen.operand(searchValues.get(i));
}
- Value result = gen.getLIRGeneratorTool().emitArrayIndexOf(kind, findTwoConsecutive, gen.operand(arrayPointer), gen.operand(arrayLength), searchValueOperands);
+ Value result = gen.getLIRGeneratorTool().emitArrayIndexOf(arrayKind, valueKind, findTwoConsecutive,
+ gen.operand(arrayPointer), gen.operand(arrayLength), gen.operand(fromIndex), searchValueOperands);
gen.setResult(this, result);
}
@@ -100,30 +106,125 @@
}
@NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, @ConstantNodeParameter boolean findTwoConsecutive,
- Pointer arrayPointer, int arrayLength, int searchValue);
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1, byte v2);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3);
@NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, char c1);
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3, byte v4);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1);
@NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, char c1, char c2);
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1, char v2);
@NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, char c1, char c2, char c3);
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1, char v2, char v3);
+
+ @NodeIntrinsic
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, char v1, char v2, char v3, char v4);
@NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, char c1, char c2, char c3, char c4);
+ private static native int optimizedArrayIndexOf(
+ @ConstantNodeParameter JavaKind arrayKind,
+ @ConstantNodeParameter JavaKind valueKind,
+ @ConstantNodeParameter boolean findTwoConsecutive,
+ Object array, int arrayLength, int fromIndex, int searchValue);
+
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, byte v1) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1);
+ }
+
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, byte v1, byte v2) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1, v2);
+ }
- @NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, byte c1);
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1, v2, v3);
+ }
+
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, byte v1, byte v2, byte v3, byte v4) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Byte, false, array, arrayLength, fromIndex, v1, v2, v3, v4);
+ }
+
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, char v1) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1);
+ }
+
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, char v1, char v2) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2);
+ }
- @NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, byte c1, byte c2);
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, char v1, char v2, char v3) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3);
+ }
+
+ public static int indexOf(byte[] array, int arrayLength, int fromIndex, char v1, char v2, char v3, char v4) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3, v4);
+ }
+
+ public static int indexOf(char[] array, int arrayLength, int fromIndex, char v1) {
+ return optimizedArrayIndexOf(JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1);
+ }
+
+ public static int indexOf(char[] array, int arrayLength, int fromIndex, char v1, char v2) {
+ return optimizedArrayIndexOf(JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2);
+ }
- @NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, byte c1, byte c2, byte c3);
+ public static int indexOf(char[] array, int arrayLength, int fromIndex, char v1, char v2, char v3) {
+ return optimizedArrayIndexOf(JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3);
+ }
+
+ public static int indexOf(char[] array, int arrayLength, int fromIndex, char v1, char v2, char v3, char v4) {
+ return optimizedArrayIndexOf(JavaKind.Char, JavaKind.Char, false, array, arrayLength, fromIndex, v1, v2, v3, v4);
+ }
- @NodeIntrinsic
- public static native int optimizedArrayIndexOf(@ConstantNodeParameter JavaKind kind, Pointer arrayPointer, int arrayLength, byte c1, byte c2, byte c3, byte c4);
+ public static int indexOf2ConsecutiveBytes(byte[] array, int arrayLength, int fromIndex, int values) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Byte, true, array, arrayLength, fromIndex, values);
+ }
+
+ public static int indexOf2ConsecutiveChars(byte[] array, int arrayLength, int fromIndex, int values) {
+ return optimizedArrayIndexOf(JavaKind.Byte, JavaKind.Char, true, array, arrayLength, fromIndex, values);
+ }
+
+ public static int indexOf2ConsecutiveChars(char[] array, int arrayLength, int fromIndex, int values) {
+ return optimizedArrayIndexOf(JavaKind.Char, JavaKind.Char, true, array, arrayLength, fromIndex, values);
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,8 +32,6 @@
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import java.util.Arrays;
@@ -62,6 +60,7 @@
import org.graalvm.compiler.replacements.nodes.FusedMultiplyAddNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
@@ -95,7 +94,7 @@
}
private static void registerThreadPlugins(InvocationPlugins plugins, AMD64 arch) {
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
// Pause instruction introduced with SSE2
if (arch.getFeatures().contains(AMD64.CPUFeature.SSE2)) {
Registration r = new Registration(plugins, Thread.class);
@@ -177,7 +176,7 @@
registerRound(r, "floor", RoundingMode.DOWN);
}
- if (useFMAIntrinsics && !Java8OrEarlier && arch.getFeatures().contains(CPUFeature.FMA)) {
+ if (useFMAIntrinsics && JavaVersionUtil.JAVA_SPEC > 8 && arch.getFeatures().contains(CPUFeature.FMA)) {
registerFMA(r);
}
}
@@ -248,7 +247,7 @@
}
private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
Registration r;
r = new Registration(plugins, String.class, replacementsBytecodeProvider);
r.setAllowOverwrite(true);
@@ -284,9 +283,10 @@
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider, boolean explicitUnsafeNullChecks) {
registerUnsafePlugins(new Registration(plugins, Unsafe.class), explicitUnsafeNullChecks, new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}, true);
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", replacementsBytecodeProvider), explicitUnsafeNullChecks,
- new JavaKind[]{JavaKind.Boolean, JavaKind.Byte, JavaKind.Char, JavaKind.Short, JavaKind.Int, JavaKind.Long, JavaKind.Object}, Java11OrEarlier);
+ new JavaKind[]{JavaKind.Boolean, JavaKind.Byte, JavaKind.Char, JavaKind.Short, JavaKind.Int, JavaKind.Long, JavaKind.Object},
+ JavaVersionUtil.JAVA_SPEC <= 11);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java Fri Jun 28 14:36:42 2019 +0530
@@ -112,12 +112,7 @@
// Note: fromIndex might be near -1>>>1.
return -1;
}
- Pointer sourcePointer = byteOffsetPointer(value, fromIndex);
- int result = AMD64ArrayIndexOf.indexOf1Byte(sourcePointer, length - fromIndex, (byte) ch);
- if (result != -1) {
- return result + fromIndex;
- }
- return result;
+ return AMD64ArrayIndexOf.indexOf1Byte(value, length, fromIndex, (byte) ch);
}
@MethodSubstitution
@@ -137,37 +132,25 @@
// The empty string contains nothing except the empty string.
return -1;
}
- int totalOffset = fromIndex;
if (targetCount == 1) {
- Pointer sourcePointer = byteOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOf1Byte(sourcePointer, sourceCount - fromIndex, target[0]);
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOf1Byte(source, sourceCount, fromIndex, target[0]);
} else if (targetCount == 2) {
- Pointer sourcePointer = byteOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveBytes(sourcePointer, sourceCount - fromIndex, target[0], target[1]);
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOfTwoConsecutiveBytes(source, sourceCount, fromIndex, target[0], target[1]);
} else {
- int haystackLength = sourceCount - (fromIndex + (targetCount - 2));
- while (haystackLength > 0) {
- Pointer sourcePointer = byteOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveBytes(sourcePointer, haystackLength, target[0], target[1]);
+ int haystackLength = sourceCount - (targetCount - 2);
+ int offset = fromIndex;
+ while (offset < haystackLength) {
+ int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveBytes(source, haystackLength, offset, target[0], target[1]);
if (indexOfResult < 0) {
return -1;
}
- totalOffset += indexOfResult;
- haystackLength -= (indexOfResult + 1);
- Pointer cmpSourcePointer = byteOffsetPointer(source, totalOffset);
+ offset = indexOfResult;
+ Pointer cmpSourcePointer = byteOffsetPointer(source, offset);
Pointer targetPointer = pointer(target);
if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Byte)) {
- return totalOffset;
+ return offset;
}
- totalOffset++;
+ offset++;
}
return -1;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Fri Jun 28 14:36:42 2019 +0530
@@ -84,29 +84,17 @@
}
if (targetCount == 1) {
- Pointer sourcePointer = Word.objectToTrackedPointer(source).add(charArrayBaseOffset(INJECTED)).add(totalOffset * charArrayIndexScale(INJECTED));
- int indexOfResult = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, target[targetOffset]);
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOf1Char(source, sourceCount, totalOffset, target[targetOffset]);
} else if (targetCount == 2) {
- Pointer sourcePointer = Word.objectToTrackedPointer(source).add(charArrayBaseOffset(INJECTED)).add(totalOffset * charArrayIndexScale(INJECTED));
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, sourceCount - fromIndex, target[targetOffset], target[targetOffset + 1]);
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(source, sourceCount, totalOffset, target[targetOffset], target[targetOffset + 1]);
} else {
- int haystackLength = sourceCount - (fromIndex + (targetCount - 2));
- while (haystackLength > 0) {
- Pointer sourcePointer = Word.objectToTrackedPointer(source).add(charArrayBaseOffset(INJECTED)).add(totalOffset * charArrayIndexScale(INJECTED));
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, haystackLength, target[targetOffset], target[targetOffset + 1]);
+ int haystackLength = sourceCount - (targetCount - 2);
+ while (totalOffset < haystackLength) {
+ int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(source, haystackLength, totalOffset, target[targetOffset], target[targetOffset + 1]);
if (indexOfResult < 0) {
return -1;
}
- totalOffset += indexOfResult;
- haystackLength -= (indexOfResult + 1);
+ totalOffset = indexOfResult;
Pointer cmpSourcePointer = Word.objectToTrackedPointer(source).add(charArrayBaseOffset(INJECTED)).add(totalOffset * charArrayIndexScale(INJECTED));
Pointer targetPointer = Word.objectToTrackedPointer(target).add(charArrayBaseOffset(INJECTED)).add(targetOffset * charArrayIndexScale(INJECTED));
if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Char)) {
@@ -133,13 +121,7 @@
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
char[] sourceArray = StringSubstitutions.getValue(source);
-
- Pointer sourcePointer = Word.objectToTrackedPointer(sourceArray).add(charArrayBaseOffset(INJECTED)).add(fromIndex * charArrayIndexScale(INJECTED));
- int result = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, (char) ch);
- if (result != -1) {
- return result + fromIndex;
- }
- return result;
+ return AMD64ArrayIndexOf.indexOf1Char(sourceArray, sourceCount, fromIndex, (char) ch);
} else {
return indexOf(source, ch, origFromIndex);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java Fri Jun 28 14:36:42 2019 +0530
@@ -103,12 +103,7 @@
@MethodSubstitution
public static int indexOfCharUnsafe(byte[] value, int ch, int fromIndex, int max) {
- Pointer sourcePointer = charOffsetPointer(value, fromIndex);
- int result = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, max - fromIndex, (char) ch);
- if (result != -1) {
- return result + fromIndex;
- }
- return result;
+ return AMD64ArrayIndexOf.indexOf1Char(value, max, fromIndex, (char) ch);
}
private static Word pointer(byte[] target) {
@@ -125,39 +120,26 @@
ReplacementsUtil.runtimeAssert(targetCount > 0, "StringUTF16.indexOfUnsafe invalid args: targetCount <= 0");
ReplacementsUtil.runtimeAssert(targetCount <= length(target), "StringUTF16.indexOfUnsafe invalid args: targetCount > length(target)");
ReplacementsUtil.runtimeAssert(sourceCount >= targetCount, "StringUTF16.indexOfUnsafe invalid args: sourceCount < targetCount");
- int totalOffset = fromIndex;
if (targetCount == 1) {
- Pointer sourcePointer = charOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, StringUTF16Substitutions.getChar(target, 0));
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOf1Char(source, sourceCount, fromIndex, StringUTF16Substitutions.getChar(target, 0));
} else if (targetCount == 2) {
- Pointer sourcePointer = charOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, sourceCount - fromIndex, StringUTF16Substitutions.getChar(target, 0),
- StringUTF16Substitutions.getChar(target, 1));
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(source, sourceCount, fromIndex, StringUTF16Substitutions.getChar(target, 0), StringUTF16Substitutions.getChar(target, 1));
} else {
- int haystackLength = sourceCount - (fromIndex + (targetCount - 2));
- while (haystackLength > 0) {
- Pointer sourcePointer = charOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, haystackLength, StringUTF16Substitutions.getChar(target, 0),
+ int haystackLength = sourceCount - (targetCount - 2);
+ int offset = fromIndex;
+ while (offset < haystackLength) {
+ int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(source, haystackLength, offset, StringUTF16Substitutions.getChar(target, 0),
StringUTF16Substitutions.getChar(target, 1));
if (indexOfResult < 0) {
return -1;
}
- totalOffset += indexOfResult;
- haystackLength -= (indexOfResult + 1);
- Pointer cmpSourcePointer = charOffsetPointer(source, totalOffset);
+ offset = indexOfResult;
+ Pointer cmpSourcePointer = charOffsetPointer(source, offset);
Pointer targetPointer = pointer(target);
if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Char)) {
- return totalOffset;
+ return offset;
}
- totalOffset++;
+ offset++;
}
return -1;
}
@@ -169,37 +151,25 @@
ReplacementsUtil.runtimeAssert(targetCount > 0, "StringUTF16.indexOfLatin1Unsafe invalid args: targetCount <= 0");
ReplacementsUtil.runtimeAssert(targetCount <= target.length, "StringUTF16.indexOfLatin1Unsafe invalid args: targetCount > length(target)");
ReplacementsUtil.runtimeAssert(sourceCount >= targetCount, "StringUTF16.indexOfLatin1Unsafe invalid args: sourceCount < targetCount");
- int totalOffset = fromIndex;
if (targetCount == 1) {
- Pointer sourcePointer = charOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOf1Char(sourcePointer, sourceCount - fromIndex, (char) Byte.toUnsignedInt(target[0]));
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOf1Char(source, sourceCount, fromIndex, (char) Byte.toUnsignedInt(target[0]));
} else if (targetCount == 2) {
- Pointer sourcePointer = charOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, sourceCount - fromIndex, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1]));
- if (indexOfResult >= 0) {
- return indexOfResult + totalOffset;
- }
- return indexOfResult;
+ return AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(source, sourceCount, fromIndex, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1]));
} else {
- int haystackLength = sourceCount - (fromIndex + (targetCount - 2));
- while (haystackLength > 0) {
- Pointer sourcePointer = charOffsetPointer(source, totalOffset);
- int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(sourcePointer, haystackLength, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1]));
+ int haystackLength = sourceCount - (targetCount - 2);
+ int offset = fromIndex;
+ while (offset < haystackLength) {
+ int indexOfResult = AMD64ArrayIndexOf.indexOfTwoConsecutiveChars(source, haystackLength, offset, (char) Byte.toUnsignedInt(target[0]), (char) Byte.toUnsignedInt(target[1]));
if (indexOfResult < 0) {
return -1;
}
- totalOffset += indexOfResult;
- haystackLength -= (indexOfResult + 1);
- Pointer cmpSourcePointer = charOffsetPointer(source, totalOffset);
+ offset = indexOfResult;
+ Pointer cmpSourcePointer = charOffsetPointer(source, offset);
Pointer targetPointer = pointer(target);
if (ArrayRegionEqualsNode.regionEquals(cmpSourcePointer, targetPointer, targetCount, JavaKind.Char, JavaKind.Byte)) {
- return totalOffset;
+ return offset;
}
- totalOffset++;
+ offset++;
}
return -1;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArraysSubstitutionsTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArraysSubstitutionsTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,7 +33,6 @@
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Assert;
@@ -133,7 +132,7 @@
StructuredGraph graph = parseEager("testCanonicalLengthSnippet", AllowAssumptions.NO);
HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
createInliningPhase().apply(graph, context);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
}
@@ -149,7 +148,7 @@
StructuredGraph graph = parseEager("testCanonicalEqualSnippet", AllowAssumptions.NO);
HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
createInliningPhase().apply(graph, context);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
}
@@ -163,9 +162,9 @@
StructuredGraph graph = parseEager("testVirtualEqualSnippet", AllowAssumptions.NO);
HighTierContext context = new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
createInliningPhase().apply(graph, context);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
}
@@ -181,9 +180,9 @@
StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", AllowAssumptions.NO);
HighTierContext context = getDefaultHighTierContext();
createInliningPhase().apply(graph, context);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context);
- new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+ new CanonicalizerPhase().apply(graph, getProviders());
Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnExceptionTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -34,6 +34,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.common.AbstractInliningPhase;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.ExportingClassLoader;
import org.junit.Assert;
import org.junit.Assume;
@@ -103,7 +104,7 @@
@Test
public void test3() {
- Assume.assumeTrue("Only works on jdk8 right now", Java8OrEarlier);
+ Assume.assumeTrue("Only works on jdk8 right now", JavaVersionUtil.JAVA_SPEC <= 8);
ResolvedJavaMethod method = getResolvedJavaMethod("test3Snippet");
for (int i = 0; i < 2; i++) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DerivedOopTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DerivedOopTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -266,8 +266,8 @@
}
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
+ protected void checkHighTierGraph(StructuredGraph graph) {
assert graph.getNodes().filter(WordCastNode.class).count() > 0 : "DerivedOopTest.toLong should be intrinsified";
- return super.checkHighTierGraph(graph);
+ super.checkHighTierGraph(graph);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -94,14 +94,13 @@
}
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
+ protected void checkHighTierGraph(StructuredGraph graph) {
// check that folding happened correctly
StartNode start = graph.start();
assert start.next() instanceof ReturnNode : "expected ReturnNode, got " + start.next();
ReturnNode ret = (ReturnNode) start.next();
assert ret.result().isConstant() : "expected ConstantNode, got " + ret.result();
- return true;
}
@Test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/InvokerSignatureMismatchTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.test;
+
+import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
+import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
+
+import org.junit.Test;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+
+import java.io.File;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+
+import org.graalvm.compiler.core.test.CustomizedBytecodePatternTest;
+import org.graalvm.compiler.test.SubprocessUtil;
+import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class InvokerSignatureMismatchTest {
+
+ @Test
+ public void test() throws Throwable {
+ List<String> args = withoutDebuggerArguments(getVMCommandLine());
+ String classPath = System.getProperty("java.class.path");
+ classPath = classPath + File.pathSeparator + TestISMBL.class.getProtectionDomain().getCodeSource().getLocation().getPath();
+ args.add("-Xbootclasspath/a:" + classPath);
+ args.add("-XX:-TieredCompilation");
+ args.add("-XX:+EnableJVMCI");
+ args.add("-XX:+UseJVMCICompiler");
+
+ args.add(TestISMBL.class.getName());
+ Subprocess proc = SubprocessUtil.java(args);
+ if (proc.exitCode != 0) {
+ System.out.println(proc);
+ }
+ }
+}
+
+class TestISMBL extends CustomizedBytecodePatternTest {
+
+ public static void main(String[] args) {
+ try {
+ new TestISMBL().test();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ private void test() throws Throwable {
+ getClass("java/lang/invoke/MHHelper");
+ Class<?> testClass = getClass("ISMTest");
+
+ ResolvedJavaMethod mL = getResolvedJavaMethod(testClass, "mainLink");
+ ResolvedJavaMethod mI = getResolvedJavaMethod(testClass, "mainInvoke");
+ executeActual(mL, null, 100);
+ executeActual(mI, null, 100);
+ }
+
+ @Override
+ protected Class<?> getClass(String className) throws ClassNotFoundException {
+ if (className.equals("java/lang/invoke/MHHelper")) {
+ return super.getClassBL(className, MethodHandles.lookup());
+ } else {
+ return super.getClass(className);
+ }
+ }
+
+ @Override
+ protected byte[] generateClass(String className) {
+ String[] exceptions = new String[]{"java/lang/Throwable"};
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+ cw.visit(52, ACC_SUPER | ACC_PUBLIC, className, null, "java/lang/Object", null);
+
+ if (className.equals("java/lang/invoke/MHHelper")) {
+ MethodVisitor internalMemberName = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "internalMemberName", "(Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;", null, exceptions);
+ internalMemberName.visitCode();
+ internalMemberName.visitVarInsn(ALOAD, 0);
+ internalMemberName.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "internalMemberName", "()Ljava/lang/invoke/MemberName;", false);
+ internalMemberName.visitInsn(ARETURN);
+ internalMemberName.visitMaxs(1, 1);
+ internalMemberName.visitEnd();
+
+ MethodVisitor linkToStatic = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "linkToStatic", "(FLjava/lang/Object;)I", null, exceptions);
+ linkToStatic.visitCode();
+ linkToStatic.visitVarInsn(FLOAD, 0);
+ linkToStatic.visitVarInsn(ALOAD, 1);
+ linkToStatic.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandle", "linkToStatic", "(FLjava/lang/Object;)I", false);
+ linkToStatic.visitInsn(IRETURN);
+ linkToStatic.visitMaxs(1, 1);
+ linkToStatic.visitEnd();
+
+ MethodVisitor invokeBasicI = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invokeBasicI", "(Ljava/lang/invoke/MethodHandle;F)I", null, exceptions);
+ invokeBasicI.visitCode();
+ invokeBasicI.visitVarInsn(ALOAD, 0);
+ invokeBasicI.visitVarInsn(FLOAD, 1);
+ invokeBasicI.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeBasic", "(F)I", false);
+ invokeBasicI.visitInsn(IRETURN);
+ invokeBasicI.visitMaxs(1, 1);
+ invokeBasicI.visitEnd();
+
+ } else {
+ assert className.equals("ISMTest") : className;
+ cw.visitField(ACC_FINAL | ACC_STATIC, "INT_MH", "Ljava/lang/invoke/MethodHandle;", null, null).visitAnnotation("Ljava/lang/invoke/Stable.class;", true).visitEnd();
+ MethodVisitor clinit = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, exceptions);
+ clinit.visitCode();
+ clinit.visitInsn(ACONST_NULL);
+ clinit.visitVarInsn(ASTORE, 0);
+ clinit.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false);
+ clinit.visitLdcInsn(Type.getObjectType(className));
+ clinit.visitLdcInsn("bodyI");
+ clinit.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
+ clinit.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
+ clinit.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodType", "methodType", "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType;", false);
+ clinit.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStatic",
+ "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;", false);
+ clinit.visitFieldInsn(PUTSTATIC, className, "INT_MH", "Ljava/lang/invoke/MethodHandle;");
+ clinit.visitInsn(RETURN);
+ clinit.visitMaxs(1, 1);
+ clinit.visitEnd();
+
+ MethodVisitor mainLink = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "mainLink", "(I)I", null, exceptions);
+ mainLink.visitCode();
+ mainLink.visitFieldInsn(GETSTATIC, className, "INT_MH", "Ljava/lang/invoke/MethodHandle;");
+ mainLink.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MHHelper", "internalMemberName", "(Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;", false);
+ mainLink.visitVarInsn(ASTORE, 1);
+ mainLink.visitVarInsn(ILOAD, 0);
+ mainLink.visitInsn(I2F);
+ mainLink.visitVarInsn(ALOAD, 1);
+ mainLink.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MHHelper", "linkToStatic", "(FLjava/lang/Object;)I", false);
+ mainLink.visitInsn(IRETURN);
+ mainLink.visitMaxs(1, 1);
+ mainLink.visitEnd();
+
+ MethodVisitor mainInvoke = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "mainInvoke", "(I)I", null, exceptions);
+ mainInvoke.visitCode();
+ mainInvoke.visitFieldInsn(GETSTATIC, className, "INT_MH", "Ljava/lang/invoke/MethodHandle;");
+ mainInvoke.visitVarInsn(ILOAD, 0);
+ mainInvoke.visitInsn(I2F);
+ mainInvoke.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MHHelper", "invokeBasicI", "(Ljava/lang/invoke/MethodHandle;F)I", false);
+ mainInvoke.visitInsn(IRETURN);
+ mainInvoke.visitMaxs(1, 1);
+ mainInvoke.visitEnd();
+
+ MethodVisitor bodyI = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "bodyI", "(I)I", null, null);
+ bodyI.visitCode();
+ bodyI.visitVarInsn(ILOAD, 0);
+ bodyI.visitIntInsn(SIPUSH, 1023);
+ bodyI.visitInsn(IAND);
+ bodyI.visitInsn(IRETURN);
+ bodyI.visitMaxs(1, 1);
+ bodyI.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,9 +43,9 @@
import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.replacements.CachingPEGraphDecoder;
import jdk.internal.vm.compiler.word.LocationIdentity;
import org.junit.Test;
@@ -138,13 +138,13 @@
registerPlugins(graphBuilderConfig.getPlugins().getInvocationPlugins());
targetGraph = new StructuredGraph.Builder(getInitialOptions(), debug, AllowAssumptions.YES).method(testMethod).build();
CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(getTarget().arch, targetGraph, getProviders(), graphBuilderConfig, OptimisticOptimizations.NONE, AllowAssumptions.YES,
- null, null, new InlineInvokePlugin[]{new InlineAll()}, null, null, null, null);
+ null, null, new InlineInvokePlugin[]{new InlineAll()}, null, null, null, null, null);
decoder.decode(testMethod, false, false);
debug.dump(DebugContext.BASIC_LEVEL, targetGraph, "Target Graph");
targetGraph.verify();
- PhaseContext context = new PhaseContext(getProviders());
+ CoreProviders context = getProviders();
new CanonicalizerPhase().apply(targetGraph, context);
targetGraph.verify();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -69,7 +69,7 @@
import org.graalvm.compiler.phases.common.GuardLoweringPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.test.GraalTest;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.internal.vm.compiler.word.LocationIdentity;
import org.junit.Assert;
import org.junit.Assume;
@@ -375,7 +375,7 @@
@Test
public void testNextAfter() {
- Assume.assumeFalse(GraalTest.Java8OrEarlier);
+ Assume.assumeFalse(JavaVersionUtil.JAVA_SPEC <= 8);
double[] inArray = new double[1024];
double[] outArray = new double[1024];
for (int i = 0; i < inArray.length; i++) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/RootMethodSubstitutionTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -34,6 +34,7 @@
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
@@ -51,7 +52,7 @@
/**
* Exercise
- * {@link org.graalvm.compiler.nodes.spi.Replacements#getIntrinsicGraph(ResolvedJavaMethod, CompilationIdentifier, DebugContext)}
+ * {@link org.graalvm.compiler.nodes.spi.Replacements#getIntrinsicGraph(ResolvedJavaMethod, CompilationIdentifier, DebugContext, Cancellable)}
* with regular method substitutions and encoded graphs.
*/
@RunWith(Parameterized.class)
@@ -113,14 +114,14 @@
private StructuredGraph getIntrinsicGraph(boolean useEncodedGraphs) {
OptionValues options = new OptionValues(getDebugContext().getOptions(), GraalOptions.UseEncodedGraphs, useEncodedGraphs);
DebugContext debugContext = DebugContext.create(options, getDebugContext().getDescription(), getDebugHandlersFactories());
- return getReplacements().getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, debugContext);
+ return getReplacements().getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, debugContext, null);
}
StructuredGraph expectedGraph;
StructuredGraph actualGraph;
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
+ protected void checkHighTierGraph(StructuredGraph graph) {
// Capture the graphs after high tier
if (expectedGraph == null) {
expectedGraph = (StructuredGraph) graph.copy(graph.getDebug());
@@ -128,7 +129,7 @@
assert actualGraph == null;
actualGraph = (StructuredGraph) graph.copy(graph.getDebug());
}
- return super.checkHighTierGraph(graph);
+ super.checkHighTierGraph(graph);
}
@Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -91,7 +91,7 @@
OptionValues options;
boolean needCheckNode = true;
- if (JavaVersionUtil.Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
needCheckNode = false;
} else {
List<String> vmArgs = GraalServices.getInputArguments();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompressInflateTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -35,6 +35,7 @@
import org.graalvm.compiler.replacements.amd64.AMD64StringLatin1Substitutions;
import org.graalvm.compiler.replacements.amd64.AMD64StringUTF16CompressNode;
import org.graalvm.compiler.replacements.amd64.AMD64StringUTF16Substitutions;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +56,7 @@
@Before
public void checkAMD64() {
- assumeFalse(Java8OrEarlier);
+ assumeFalse(JavaVersionUtil.JAVA_SPEC <= 8);
// Test case is (currently) AMD64 only.
assumeTrue(getTarget().arch instanceof AMD64);
}
@@ -114,7 +115,7 @@
Class<?> javaclass = Class.forName("java.lang.StringLatin1");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
- StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+ StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), null);
assertInGraph(graph, AMD64StringLatin1InflateNode.class);
InstalledCode code = getCode(caller, graph);
@@ -152,7 +153,7 @@
Class<?> javaclass = Class.forName("java.lang.StringLatin1");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
- StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+ StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), null);
assertInGraph(graph, AMD64StringLatin1InflateNode.class);
InstalledCode code = getCode(caller, graph);
@@ -217,7 +218,7 @@
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
- StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+ StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), null);
assertInGraph(graph, AMD64StringUTF16CompressNode.class);
InstalledCode code = getCode(caller, graph);
@@ -253,7 +254,7 @@
Class<?> javaclass = Class.forName("java.lang.StringUTF16");
ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "compress", char[].class, int.class, byte[].class, int.class, int.class);
- StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+ StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), null);
assertInGraph(graph, AMD64StringUTF16CompressNode.class);
InstalledCode code = getCode(caller, graph);
@@ -299,7 +300,7 @@
TestMethods(String testmname, Class<?> javaclass, Class<?> intrinsicClass, String javamname, Class<?>... params) {
javamethod = getResolvedJavaMethod(javaclass, javamname, params);
testmethod = getResolvedJavaMethod(testmname);
- testgraph = getReplacements().getIntrinsicGraph(javamethod, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+ testgraph = getReplacements().getIntrinsicGraph(javamethod, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), null);
assertInGraph(testgraph, intrinsicClass);
assert javamethod != null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringSubstitutionsTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -27,6 +27,7 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.replacements.StringSubstitutions;
import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.junit.Test;
import jdk.vm.ci.code.InstalledCode;
@@ -65,7 +66,7 @@
@Test
public void testEquals() {
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
// StringSubstitutions are disabled in 1.9
return;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SubstitutionsTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -130,7 +130,7 @@
}
@Override
- protected boolean checkHighTierGraph(StructuredGraph graph) {
+ protected void checkHighTierGraph(StructuredGraph graph) {
// Check that the graph contains the expected test nodes.
NodeIterable<ReturnNode> retNodes = graph.getNodes().filter(ReturnNode.class);
Assert.assertTrue("expected exactly one ReturnNode", retNodes.count() == 1);
@@ -151,8 +151,6 @@
value.safeDelete();
guard.safeDelete();
graph.removeFixed(memory);
-
- return true;
}
@Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -109,6 +109,7 @@
import org.graalvm.compiler.replacements.classfile.ClassfileBytecode;
import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import jdk.vm.ci.meta.ConstantPool;
import jdk.vm.ci.meta.JavaField;
@@ -153,7 +154,7 @@
Assume.assumeTrue(VerifyPhase.class.desiredAssertionStatus());
- String propertyName = Java8OrEarlier ? "sun.boot.class.path" : "jdk.module.path";
+ String propertyName = JavaVersionUtil.JAVA_SPEC <= 8 ? "sun.boot.class.path" : "jdk.module.path";
String bootclasspath = System.getProperty(propertyName);
Assert.assertNotNull("Cannot find value of " + propertyName, bootclasspath);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -54,6 +54,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
import org.graalvm.compiler.replacements.test.ReplacementsTest;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
import org.junit.Assert;
import org.junit.Test;
@@ -110,7 +111,7 @@
return;
}
String recursionPropName = getClass().getName() + ".recursion";
- if (Java8OrEarlier || Boolean.getBoolean(recursionPropName)) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8 || Boolean.getBoolean(recursionPropName)) {
testHelper();
} else {
List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
@@ -206,7 +207,7 @@
assumeTrue("VM name not in <pid>@<host> format: " + vmName, p != -1);
String pid = vmName.substring(0, p);
Class<?> c;
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
ClassLoader cl = ToolProvider.getSystemToolClassLoader();
c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl);
} else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Fri Jun 28 14:36:42 2019 +0530
@@ -46,9 +46,10 @@
import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
+import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.phases.util.Providers;
import jdk.vm.ci.code.Architecture;
@@ -65,11 +66,13 @@
protected final OptimisticOptimizations optimisticOpts;
private final AllowAssumptions allowAssumptions;
private final EconomicMap<ResolvedJavaMethod, EncodedGraph> graphCache;
+ private final BasePhase<? super CoreProviders> postParsingPhase;
public CachingPEGraphDecoder(Architecture architecture, StructuredGraph graph, Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts,
AllowAssumptions allowAssumptions, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins,
ParameterPlugin parameterPlugin,
- NodePlugin[] nodePlugins, ResolvedJavaMethod callInlinedMethod, SourceLanguagePositionProvider sourceLanguagePositionProvider) {
+ NodePlugin[] nodePlugins, ResolvedJavaMethod callInlinedMethod, SourceLanguagePositionProvider sourceLanguagePositionProvider,
+ BasePhase<? super CoreProviders> postParsingPhase) {
super(architecture, graph, providers, loopExplosionPlugin,
invocationPlugins, inlineInvokePlugins, parameterPlugin, nodePlugins, callInlinedMethod, sourceLanguagePositionProvider);
@@ -77,6 +80,7 @@
this.graphBuilderConfig = graphBuilderConfig;
this.optimisticOpts = optimisticOpts;
this.allowAssumptions = allowAssumptions;
+ this.postParsingPhase = postParsingPhase;
this.graphCache = EconomicMap.create();
}
@@ -90,7 +94,7 @@
if (isSubstitution && (UseEncodedGraphs.getValue(options) || IS_IN_NATIVE_IMAGE)) {
// These must go through Replacements to find the graph to use.
graphToEncode = providers.getReplacements().getMethodSubstitution(plugin, method, INLINE_AFTER_PARSING, allowAssumptions,
- options);
+ null, options);
} else {
graphToEncode = buildGraph(method, plugin, intrinsicBytecodeProvider, isSubstitution);
}
@@ -101,8 +105,7 @@
* initial graph.
*/
try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) {
- PhaseContext context = new PhaseContext(providers);
- new ConvertDeoptimizeToGuardPhase().apply(graphToEncode, context);
+ new ConvertDeoptimizeToGuardPhase().apply(graphToEncode, providers);
} catch (Throwable t) {
throw debug.handle(t);
}
@@ -125,13 +128,14 @@
// @formatter:on
try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) {
IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null
- ? new IntrinsicContext(method, plugin.getSubstitute(providers.getMetaAccess()), intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null;
+ ? new IntrinsicContext(method, plugin.getSubstitute(providers.getMetaAccess()), intrinsicBytecodeProvider, INLINE_AFTER_PARSING)
+ : null;
GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext);
graphBuilderPhaseInstance.apply(graphToEncode);
-
- PhaseContext context = new PhaseContext(providers);
- new CanonicalizerPhase().apply(graphToEncode, context);
-
+ new CanonicalizerPhase().apply(graphToEncode, providers);
+ if (postParsingPhase != null) {
+ postParsingPhase.apply(graphToEncode, providers);
+ }
} catch (Throwable ex) {
throw debug.handle(ex);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantBindingParameterPlugin.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantBindingParameterPlugin.java Fri Jun 28 14:36:42 2019 +0530
@@ -55,26 +55,28 @@
@Override
public FloatingNode interceptParameter(GraphBuilderTool b, int index, StampPair stamp) {
- Object arg = constantArgs[index];
- if (arg != null) {
- ConstantNode constantNode;
- if (arg instanceof ConstantNode) {
- ConstantNode otherCon = (ConstantNode) arg;
- if (otherCon.graph() != b.getGraph()) {
- /*
- * This is a node from another graph, so copy over extra state into a new
- * ConstantNode.
- */
- constantNode = ConstantNode.forConstant(stamp.getTrustedStamp(), otherCon.getValue(), otherCon.getStableDimension(), otherCon.isDefaultStable(), metaAccess);
+ if (index < constantArgs.length) {
+ Object arg = constantArgs[index];
+ if (arg != null) {
+ ConstantNode constantNode;
+ if (arg instanceof ConstantNode) {
+ ConstantNode otherCon = (ConstantNode) arg;
+ if (otherCon.graph() != b.getGraph()) {
+ /*
+ * This is a node from another graph, so copy over extra state into a new
+ * ConstantNode.
+ */
+ constantNode = ConstantNode.forConstant(stamp.getTrustedStamp(), otherCon.getValue(), otherCon.getStableDimension(), otherCon.isDefaultStable(), metaAccess);
+ } else {
+ constantNode = otherCon;
+ }
+ } else if (arg instanceof Constant) {
+ constantNode = ConstantNode.forConstant(stamp.getTrustedStamp(), (Constant) arg, metaAccess);
} else {
- constantNode = otherCon;
+ constantNode = ConstantNode.forConstant(snippetReflection.forBoxed(stamp.getTrustedStamp().getStackKind(), arg), metaAccess);
}
- } else if (arg instanceof Constant) {
- constantNode = ConstantNode.forConstant(stamp.getTrustedStamp(), (Constant) arg, metaAccess);
- } else {
- constantNode = ConstantNode.forConstant(snippetReflection.forBoxed(stamp.getTrustedStamp().getStackKind(), arg), metaAccess);
+ return constantNode;
}
- return constantNode;
}
return null;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Fri Jun 28 14:36:42 2019 +0530
@@ -48,7 +48,6 @@
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
-import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -140,7 +139,6 @@
import org.graalvm.compiler.replacements.SnippetLowerableMemoryNode.SnippetLowering;
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
-import org.graalvm.compiler.word.WordTypes;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CodeUtil;
@@ -166,7 +164,6 @@
protected final TargetDescription target;
private final boolean useCompressedOops;
private final ResolvedJavaType objectArrayType;
- private final WordTypes wordTypes;
private BoxingSnippets.Templates boxingSnippets;
private ConstantStringIndexOfSnippets.Templates indexOfSnippets;
@@ -177,7 +174,6 @@
this.target = target;
this.useCompressedOops = useCompressedOops;
this.objectArrayType = metaAccess.lookupJavaType(Object[].class);
- this.wordTypes = new WordTypes(metaAccess, target.wordJavaKind);
}
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) {
@@ -436,6 +432,10 @@
}
public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index) {
+ return createArrayAddress(graph, array, elementKind, elementKind, index);
+ }
+
+ public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, JavaKind arrayKind, JavaKind elementKind, ValueNode index) {
ValueNode wordIndex;
if (target.wordSize > 4) {
wordIndex = graph.unique(new SignExtendNode(index, target.wordSize * 8));
@@ -447,14 +447,14 @@
int shift = CodeUtil.log2(metaAccess.getArrayIndexScale(elementKind));
ValueNode scaledIndex = graph.unique(new LeftShiftNode(wordIndex, ConstantNode.forInt(shift, graph)));
- int base = metaAccess.getArrayBaseOffset(elementKind);
+ int base = metaAccess.getArrayBaseOffset(arrayKind);
ValueNode offset = graph.unique(new AddNode(scaledIndex, ConstantNode.forIntegerKind(target.wordJavaKind, base, graph)));
return graph.unique(new OffsetAddressNode(array, offset));
}
protected void lowerIndexAddressNode(IndexAddressNode indexAddress) {
- AddressNode lowered = createArrayAddress(indexAddress.graph(), indexAddress.getArray(), indexAddress.getElementKind(), indexAddress.getIndex());
+ AddressNode lowered = createArrayAddress(indexAddress.graph(), indexAddress.getArray(), indexAddress.getArrayKind(), indexAddress.getElementKind(), indexAddress.getIndex());
indexAddress.replaceAndDelete(lowered);
}
@@ -517,7 +517,7 @@
AddressNode address = createArrayIndexAddress(graph, array, elementKind, storeIndexed.index(), boundsCheck);
WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(elementKind), implicitStoreConvert(graph, elementKind, value),
- arrayStoreBarrierType(array, storeIndexed.elementKind())));
+ arrayStoreBarrierType(storeIndexed.elementKind())));
memoryWrite.setGuard(boundsCheck);
if (condition != null) {
tool.createGuard(storeIndexed, condition, DeoptimizationReason.ArrayStoreException, DeoptimizationAction.InvalidateReprofile);
@@ -792,11 +792,11 @@
long offset = fieldOffset(field);
if (offset >= 0) {
address = createOffsetAddress(graph, newObject, offset);
- barrierType = fieldInitializationBarrier(field);
+ barrierType = fieldInitializationBarrier(entryKind);
}
} else {
address = createOffsetAddress(graph, newObject, metaAccess.getArrayBaseOffset(entryKind) + i * metaAccess.getArrayIndexScale(entryKind));
- barrierType = arrayInitializationBarrier(newObject, entryKind);
+ barrierType = arrayInitializationBarrier(entryKind);
}
if (address != null) {
WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType);
@@ -829,7 +829,7 @@
barrierType = fieldStoreBarrierType(virtualInstance.field(i));
} else {
address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph));
- barrierType = arrayStoreBarrierType(newObject, virtual.entryKind(i));
+ barrierType = arrayStoreBarrierType(virtual.entryKind(i));
}
if (address != null) {
WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType);
@@ -943,50 +943,25 @@
}
protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) {
- JavaKind fieldKind = wordTypes.asKind(field.getType());
- if (fieldKind == JavaKind.Object) {
+ if (getStorageKind(field) == JavaKind.Object) {
return BarrierType.FIELD;
}
return BarrierType.NONE;
}
- /**
- * If the given value is indeed an array, and its elements are of a word type, return the
- * correct word kind; in all other cases, return the defaultElementKind. This is needed for
- * determining the correct write barrier type.
- *
- * @param array a value that is expected to have an array stamp
- * @param defaultElementKind the array's element kind without taking word types into account
- * @return the element kind of the array taking word types into account
- */
- protected JavaKind maybeWordArrayElementKind(ValueNode array, JavaKind defaultElementKind) {
- JavaKind elementKind = defaultElementKind;
- Stamp arrayStamp = array.stamp(NodeView.DEFAULT);
- if (arrayStamp instanceof AbstractObjectStamp && arrayStamp.hasValues()) {
- ResolvedJavaType arrayType = ((AbstractObjectStamp) arrayStamp).type();
- if (arrayType != null && arrayType.getComponentType() != null) {
- elementKind = wordTypes.asKind(arrayType.getComponentType());
- }
- }
- return elementKind;
- }
-
- protected BarrierType arrayStoreBarrierType(ValueNode array, JavaKind elementKind) {
- JavaKind kind = maybeWordArrayElementKind(array, elementKind);
- if (kind == JavaKind.Object) {
+ protected BarrierType arrayStoreBarrierType(JavaKind elementKind) {
+ if (elementKind == JavaKind.Object) {
return BarrierType.ARRAY;
}
return BarrierType.NONE;
}
- public BarrierType fieldInitializationBarrier(ResolvedJavaField field) {
- JavaKind fieldKind = wordTypes.asKind(field.getType());
- return fieldKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE;
+ public BarrierType fieldInitializationBarrier(JavaKind entryKind) {
+ return entryKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE;
}
- public BarrierType arrayInitializationBarrier(ValueNode array, JavaKind entryKind) {
- JavaKind kind = maybeWordArrayElementKind(array, entryKind);
- return kind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE;
+ public BarrierType arrayInitializationBarrier(JavaKind entryKind) {
+ return entryKind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE;
}
private BarrierType unsafeStoreBarrierType(RawStoreNode store) {
@@ -1002,9 +977,7 @@
// Array types must use a precise barrier, so if the type is unknown or is a supertype
// of Object[] then treat it as an array.
if (type != null && type.isArray()) {
- return arrayStoreBarrierType(object, JavaKind.Object);
- } else if (type != null && wordTypes.isWord(type)) {
- return BarrierType.NONE;
+ return BarrierType.ARRAY;
} else if (type == null || type.isAssignableFrom(objectArrayType)) {
return BarrierType.UNKNOWN;
} else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/Log.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.replacements;
-
-import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring;
-
-import java.io.PrintStream;
-
-import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
-import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
-import org.graalvm.compiler.graph.Node.NodeIntrinsic;
-import org.graalvm.compiler.nodes.extended.ForeignCallNode;
-import org.graalvm.compiler.word.Word;
-
-import jdk.vm.ci.meta.JavaKind;
-
-//JaCoCo Exclude
-
-/**
- * Provides {@link PrintStream}-like logging facility.
- */
-public final class Log {
-
- public static final ForeignCallDescriptor LOG_PRIMITIVE = new ForeignCallDescriptor("logPrimitive", void.class, int.class, long.class, boolean.class);
- public static final ForeignCallDescriptor LOG_OBJECT = new ForeignCallDescriptor("logObject", void.class, Object.class, boolean.class, boolean.class);
- public static final ForeignCallDescriptor LOG_PRINTF = new ForeignCallDescriptor("logPrintf", void.class, Word.class, long.class, long.class, long.class);
-
- @NodeIntrinsic(ForeignCallNode.class)
- private static native void log(@ConstantNodeParameter ForeignCallDescriptor logObject, Object object, boolean asString, boolean newline);
-
- @NodeIntrinsic(ForeignCallNode.class)
- private static native void log(@ConstantNodeParameter ForeignCallDescriptor logPrimitive, int typeChar, long value, boolean newline);
-
- @NodeIntrinsic(ForeignCallNode.class)
- private static native void printf(@ConstantNodeParameter ForeignCallDescriptor logPrintf, Word format, long v1, long v2, long v3);
-
- public static void print(boolean value) {
- log(LOG_PRIMITIVE, JavaKind.Boolean.getTypeChar(), value ? 1L : 0L, false);
- }
-
- public static void print(byte value) {
- log(LOG_PRIMITIVE, JavaKind.Byte.getTypeChar(), value, false);
- }
-
- public static void print(char value) {
- log(LOG_PRIMITIVE, JavaKind.Char.getTypeChar(), value, false);
- }
-
- public static void print(short value) {
- log(LOG_PRIMITIVE, JavaKind.Short.getTypeChar(), value, false);
- }
-
- public static void print(int value) {
- log(LOG_PRIMITIVE, JavaKind.Int.getTypeChar(), value, false);
- }
-
- public static void print(long value) {
- log(LOG_PRIMITIVE, JavaKind.Long.getTypeChar(), value, false);
- }
-
- /**
- * Prints a formatted string to the log stream.
- *
- * @param format a C style printf format value that can contain at most one conversion specifier
- * (i.e., a sequence of characters starting with '%').
- * @param value the value associated with the conversion specifier
- */
- public static void printf(String format, long value) {
- printf(LOG_PRINTF, cstring(format), value, 0L, 0L);
- }
-
- public static void printf(String format, long v1, long v2) {
- printf(LOG_PRINTF, cstring(format), v1, v2, 0L);
- }
-
- public static void printf(String format, long v1, long v2, long v3) {
- printf(LOG_PRINTF, cstring(format), v1, v2, v3);
- }
-
- public static void print(float value) {
- if (Float.isNaN(value)) {
- print("NaN");
- } else if (value == Float.POSITIVE_INFINITY) {
- print("Infinity");
- } else if (value == Float.NEGATIVE_INFINITY) {
- print("-Infinity");
- } else {
- log(LOG_PRIMITIVE, JavaKind.Float.getTypeChar(), Float.floatToRawIntBits(value), false);
- }
- }
-
- public static void print(double value) {
- if (Double.isNaN(value)) {
- print("NaN");
- } else if (value == Double.POSITIVE_INFINITY) {
- print("Infinity");
- } else if (value == Double.NEGATIVE_INFINITY) {
- print("-Infinity");
- } else {
- log(LOG_PRIMITIVE, JavaKind.Double.getTypeChar(), Double.doubleToRawLongBits(value), false);
- }
- }
-
- public static void print(String value) {
- log(LOG_OBJECT, value, true, false);
- }
-
- public static void printObject(Object o) {
- log(LOG_OBJECT, o, false, false);
- }
-
- public static void println(boolean value) {
- log(LOG_PRIMITIVE, JavaKind.Boolean.getTypeChar(), value ? 1L : 0L, true);
- }
-
- public static void println(byte value) {
- log(LOG_PRIMITIVE, JavaKind.Byte.getTypeChar(), value, true);
- }
-
- public static void println(char value) {
- log(LOG_PRIMITIVE, JavaKind.Char.getTypeChar(), value, true);
- }
-
- public static void println(short value) {
- log(LOG_PRIMITIVE, JavaKind.Short.getTypeChar(), value, true);
- }
-
- public static void println(int value) {
- log(LOG_PRIMITIVE, JavaKind.Int.getTypeChar(), value, true);
- }
-
- public static void println(long value) {
- log(LOG_PRIMITIVE, JavaKind.Long.getTypeChar(), value, true);
- }
-
- public static void println(float value) {
- if (Float.isNaN(value)) {
- println("NaN");
- } else if (value == Float.POSITIVE_INFINITY) {
- println("Infinity");
- } else if (value == Float.NEGATIVE_INFINITY) {
- println("-Infinity");
- } else {
- log(LOG_PRIMITIVE, JavaKind.Float.getTypeChar(), Float.floatToRawIntBits(value), true);
- }
- }
-
- public static void println(double value) {
- if (Double.isNaN(value)) {
- println("NaN");
- } else if (value == Double.POSITIVE_INFINITY) {
- println("Infinity");
- } else if (value == Double.NEGATIVE_INFINITY) {
- println("-Infinity");
- } else {
- log(LOG_PRIMITIVE, JavaKind.Double.getTypeChar(), Double.doubleToRawLongBits(value), true);
- }
- }
-
- public static void println(String value) {
- log(LOG_OBJECT, value, true, true);
- }
-
- public static void printlnObject(Object o) {
- log(LOG_OBJECT, o, false, true);
- }
-
- public static void println() {
- println("");
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Fri Jun 28 14:36:42 2019 +0530
@@ -67,6 +67,7 @@
import org.graalvm.compiler.java.GraphBuilderPhase.Instance;
import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.nodes.CallTargetNode;
+import org.graalvm.compiler.nodes.Cancellable;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -86,7 +87,6 @@
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordOperationPlugin;
@@ -263,7 +263,7 @@
@Override
public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context,
- StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
+ StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) {
// Method substitutions are parsed by the BytecodeParser.
return null;
}
@@ -330,7 +330,7 @@
@SuppressWarnings("try")
@Override
- public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) {
+ public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug, Cancellable cancellable) {
MethodSubstitutionPlugin msPlugin = getMethodSubstitution(method);
if (msPlugin != null) {
ResolvedJavaMethod substMethod = msPlugin.getSubstitute(providers.getMetaAccess());
@@ -560,7 +560,7 @@
createGraphBuilder(replacements.providers, config, OptimisticOptimizations.NONE, initialIntrinsicContext).apply(graph);
- new CanonicalizerPhase().apply(graph, new PhaseContext(replacements.providers));
+ new CanonicalizerPhase().apply(graph, replacements.providers);
} catch (Throwable e) {
throw debug.handle(e);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Fri Jun 28 14:36:42 2019 +0530
@@ -119,6 +119,7 @@
import org.graalvm.compiler.nodes.memory.MemoryNode;
import org.graalvm.compiler.nodes.memory.MemoryPhiNode;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.nodes.spi.MemoryProxy;
import org.graalvm.compiler.nodes.util.GraphUtil;
@@ -133,7 +134,6 @@
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.RemoveValueProxyPhase;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
import org.graalvm.compiler.replacements.nodes.LoadSnippetVarargParameterNode;
@@ -633,6 +633,10 @@
}
}
+ public Providers getProviders() {
+ return providers;
+ }
+
public static Method findMethod(Class<? extends Snippets> declaringClass, String methodName, Method except) {
for (Method m : declaringClass.getDeclaredMethods()) {
if (m.getName().equals(methodName) && !m.equals(except)) {
@@ -698,7 +702,7 @@
* Gets a template for a given key, creating it first if necessary.
*/
@SuppressWarnings("try")
- protected SnippetTemplate template(ValueNode replacee, final Arguments args) {
+ public SnippetTemplate template(ValueNode replacee, final Arguments args) {
StructuredGraph graph = replacee.graph();
DebugContext outer = graph.getDebug();
SnippetTemplate template = Options.UseSnippetTemplateCache.getValue(options) && args.cacheable ? templates.get(args.cacheKey) : null;
@@ -770,8 +774,6 @@
ResolvedJavaMethod method = snippetGraph.method();
Signature signature = method.getSignature();
- PhaseContext phaseContext = new PhaseContext(providers);
-
// Copy snippet graph, replacing constant parameters with given arguments
final StructuredGraph snippetCopy = new StructuredGraph.Builder(options, debug).name(snippetGraph.name).method(snippetGraph.method()).trackNodeSourcePosition(
snippetGraph.trackNodeSourcePosition()).setIsSubstitution(true).build();
@@ -880,7 +882,7 @@
}
}
- explodeLoops(snippetCopy, phaseContext);
+ explodeLoops(snippetCopy, providers);
GuardsStage guardsStage = args.cacheKey.guardsStage;
// Perform lowering on the snippet
@@ -889,7 +891,7 @@
}
snippetCopy.setGuardsStage(guardsStage);
try (DebugContext.Scope s = debug.scope("LoweringSnippetTemplate", snippetCopy)) {
- new LoweringPhase(new CanonicalizerPhase(), args.cacheKey.loweringStage).apply(snippetCopy, phaseContext);
+ new LoweringPhase(new CanonicalizerPhase(), args.cacheKey.loweringStage).apply(snippetCopy, providers);
} catch (Throwable e) {
throw debug.handle(e);
}
@@ -1045,7 +1047,7 @@
return true;
}
- public static void explodeLoops(final StructuredGraph snippetCopy, PhaseContext phaseContext) {
+ public static void explodeLoops(final StructuredGraph snippetCopy, CoreProviders providers) {
// Do any required loop explosion
boolean exploded = false;
do {
@@ -1057,8 +1059,8 @@
if (loopBegin != null) {
LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
Mark mark = snippetCopy.getMark();
- LoopTransformations.fullUnroll(loop, phaseContext, new CanonicalizerPhase());
- new CanonicalizerPhase().applyIncremental(snippetCopy, phaseContext, mark, false);
+ LoopTransformations.fullUnroll(loop, providers, new CanonicalizerPhase());
+ new CanonicalizerPhase().applyIncremental(snippetCopy, providers, mark, false);
loop.deleteUnusedNodes();
}
GraphUtil.removeFixedWithUnusedInputs(explodeLoop);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Fri Jun 28 14:36:42 2019 +0530
@@ -33,8 +33,6 @@
import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
import static org.graalvm.compiler.nodes.NamedLocationIdentity.OFF_HEAP_LOCATION;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -133,6 +131,7 @@
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactOverflowNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactSplitNode;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup;
import jdk.internal.vm.compiler.word.LocationIdentity;
@@ -188,7 +187,7 @@
Field coder = null;
try {
STRING_VALUE_FIELD = String.class.getDeclaredField("value");
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
coder = String.class.getDeclaredField("coder");
}
} catch (NoSuchFieldException e) {
@@ -227,7 +226,7 @@
}
});
- if (Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
r.registerMethodSubstitution(StringSubstitutions.class, "equals", Receiver.class, Object.class);
r.register7("indexOf", char[].class, int.class, int.class, char[].class, int.class, int.class, int.class, new StringIndexOfConstantPlugin());
@@ -384,7 +383,7 @@
public static void registerPlatformSpecificUnsafePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, JavaKind[] supportedCasKinds) {
registerPlatformSpecificUnsafePlugins(supportedCasKinds, new Registration(plugins, Unsafe.class), true, explicitUnsafeNullChecks);
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
registerPlatformSpecificUnsafePlugins(supportedCasKinds, new Registration(plugins, "jdk.internal.misc.Unsafe", bytecodeProvider), false, explicitUnsafeNullChecks);
}
@@ -394,14 +393,14 @@
if (java8OrEarlier) {
unsafeCompareAndSwapPluginsRegistrar.register(r, "compareAndSwap", explicitUnsafeNullChecks, new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}, true);
} else {
- unsafeCompareAndSwapPluginsRegistrar.register(r, "compareAndSet", explicitUnsafeNullChecks, supportedCasKinds, Java11OrEarlier);
- unsafeCompareAndExchangePluginsRegistrar.register(r, "compareAndExchange", explicitUnsafeNullChecks, supportedCasKinds, Java11OrEarlier);
+ unsafeCompareAndSwapPluginsRegistrar.register(r, "compareAndSet", explicitUnsafeNullChecks, supportedCasKinds, JavaVersionUtil.JAVA_SPEC <= 11);
+ unsafeCompareAndExchangePluginsRegistrar.register(r, "compareAndExchange", explicitUnsafeNullChecks, supportedCasKinds, JavaVersionUtil.JAVA_SPEC <= 11);
}
}
private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks) {
registerUnsafePlugins(new Registration(plugins, Unsafe.class), true, explicitUnsafeNullChecks);
- if (!Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
registerUnsafePlugins(new Registration(plugins, "jdk.internal.misc.Unsafe", bytecodeProvider), false, explicitUnsafeNullChecks);
}
}
@@ -410,7 +409,7 @@
for (JavaKind kind : JavaKind.values()) {
if ((kind.isPrimitive() && kind != JavaKind.Void) || kind == JavaKind.Object) {
Class<?> javaClass = kind == JavaKind.Object ? Object.class : kind.toJavaClass();
- String kindName = (kind == JavaKind.Object && !sunMiscUnsafe && !Java11OrEarlier) ? "Reference" : kind.name();
+ String kindName = (kind == JavaKind.Object && !sunMiscUnsafe && !(JavaVersionUtil.JAVA_SPEC <= 11)) ? "Reference" : kind.name();
String getName = "get" + kindName;
String putName = "put" + kindName;
// Object-based accesses
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.gc;
+
+import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
+import org.graalvm.compiler.graph.Node.NodeIntrinsic;
+import org.graalvm.compiler.nodes.NamedLocationIdentity;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
+import org.graalvm.compiler.nodes.extended.MembarNode;
+import org.graalvm.compiler.nodes.extended.NullCheckNode;
+import org.graalvm.compiler.nodes.gc.G1ArrayRangePostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ArrayRangePreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PostWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1PreWriteBarrier;
+import org.graalvm.compiler.nodes.gc.G1ReferentFieldReadBarrier;
+import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode.Address;
+import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.nodes.type.NarrowOopStamp;
+import org.graalvm.compiler.replacements.SnippetCounter;
+import org.graalvm.compiler.replacements.SnippetCounter.Group;
+import org.graalvm.compiler.replacements.SnippetTemplate;
+import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
+import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
+import org.graalvm.compiler.replacements.Snippets;
+import org.graalvm.compiler.replacements.nodes.AssertionNode;
+import org.graalvm.compiler.replacements.nodes.CStringConstant;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordFactory;
+
+public abstract class G1WriteBarrierSnippets extends WriteBarrierSnippets implements Snippets {
+
+ public static final LocationIdentity GC_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Log");
+ public static final LocationIdentity GC_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Index");
+ public static final LocationIdentity SATB_QUEUE_MARKING_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Marking");
+ public static final LocationIdentity SATB_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Index");
+ public static final LocationIdentity SATB_QUEUE_BUFFER_LOCATION = NamedLocationIdentity.mutable("GC-Queue-Buffer");
+ public static final LocationIdentity CARD_QUEUE_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Index");
+ public static final LocationIdentity CARD_QUEUE_BUFFER_LOCATION = NamedLocationIdentity.mutable("GC-Card-Queue-Buffer");
+
+ public static class Counters {
+ Counters(SnippetCounter.Group.Factory factory) {
+ Group countersWriteBarriers = factory.createSnippetCounterGroup("G1 WriteBarriers");
+ g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers");
+ g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers");
+ g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers");
+ g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers");
+ g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier",
+ "Number of effective G1 Post Write Barriers (after passing the XOR test)");
+ g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier",
+ "Number of effective G1 Post Write Barriers (after passing the NULL test)");
+ g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers");
+ }
+
+ final SnippetCounter g1AttemptedPreWriteBarrierCounter;
+ final SnippetCounter g1EffectivePreWriteBarrierCounter;
+ final SnippetCounter g1ExecutedPreWriteBarrierCounter;
+ final SnippetCounter g1AttemptedPostWriteBarrierCounter;
+ final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter;
+ final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter;
+ final SnippetCounter g1ExecutedPostWriteBarrierCounter;
+ }
+
+ @Snippet
+ public void g1PreWriteBarrier(Address address, Object object, Object expectedObject, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck,
+ @ConstantParameter int traceStartCycle, @ConstantParameter Counters counters) {
+ if (nullCheck) {
+ NullCheckNode.nullCheck(address);
+ }
+ Word thread = getThread();
+ verifyOop(object);
+ Word field = Word.fromAddress(address);
+ byte markingValue = thread.readByte(satbQueueMarkingOffset(), SATB_QUEUE_MARKING_LOCATION);
+
+ boolean trace = isTracingActive(traceStartCycle);
+ int gcCycle = 0;
+ if (trace) {
+ Pointer gcTotalCollectionsAddress = WordFactory.pointer(gcTotalCollectionsAddress());
+ gcCycle = (int) gcTotalCollectionsAddress.readLong(0);
+ log(trace, "[%d] G1-Pre Thread %p Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue());
+ log(trace, "[%d] G1-Pre Thread %p Expected Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(expectedObject).rawValue());
+ log(trace, "[%d] G1-Pre Thread %p Field %p\n", gcCycle, thread.rawValue(), field.rawValue());
+ log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue);
+ log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L);
+ }
+
+ counters.g1AttemptedPreWriteBarrierCounter.inc();
+ // If the concurrent marker is enabled, the barrier is issued.
+ if (probability(NOT_FREQUENT_PROBABILITY, markingValue != (byte) 0)) {
+ // If the previous value has to be loaded (before the write), the load is issued.
+ // The load is always issued except the cases of CAS and referent field.
+ Object previousObject;
+ if (doLoad) {
+ previousObject = field.readObject(0, BarrierType.NONE);
+ if (trace) {
+ log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(previousObject).rawValue());
+ verifyOop(previousObject);
+ }
+ } else {
+ previousObject = FixedValueAnchorNode.getObject(expectedObject);
+ }
+
+ counters.g1EffectivePreWriteBarrierCounter.inc();
+ // If the previous value is null the barrier should not be issued.
+ if (probability(FREQUENT_PROBABILITY, previousObject != null)) {
+ counters.g1ExecutedPreWriteBarrierCounter.inc();
+ // If the thread-local SATB buffer is full issue a native call which will
+ // initialize a new one and add the entry.
+ Word indexAddress = thread.add(satbQueueIndexOffset());
+ Word indexValue = indexAddress.readWord(0, SATB_QUEUE_INDEX_LOCATION);
+ if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) {
+ Word bufferAddress = thread.readWord(satbQueueBufferOffset(), SATB_QUEUE_BUFFER_LOCATION);
+ Word nextIndex = indexValue.subtract(wordSize());
+ Word logAddress = bufferAddress.add(nextIndex);
+ // Log the object to be marked as well as update the SATB's buffer next index.
+ Word previousOop = Word.objectToTrackedPointer(previousObject);
+ logAddress.writeWord(0, previousOop, GC_LOG_LOCATION);
+ indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION);
+ } else {
+ g1PreBarrierStub(previousObject);
+ }
+ }
+ }
+ }
+
+ @Snippet
+ public void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter boolean usePrecise, @ConstantParameter int traceStartCycle,
+ @ConstantParameter Counters counters) {
+ Word thread = getThread();
+ Object fixedValue = FixedValueAnchorNode.getObject(value);
+ verifyOop(object);
+ verifyOop(fixedValue);
+ validateObject(object, fixedValue);
+
+ Pointer oop;
+ if (usePrecise) {
+ oop = Word.fromAddress(address);
+ } else {
+ if (verifyBarrier()) {
+ verifyNotArray(object);
+ }
+ oop = Word.objectToTrackedPointer(object);
+ }
+
+ boolean trace = isTracingActive(traceStartCycle);
+ int gcCycle = 0;
+ if (trace) {
+ Pointer gcTotalCollectionsAddress = WordFactory.pointer(gcTotalCollectionsAddress());
+ gcCycle = (int) gcTotalCollectionsAddress.readLong(0);
+ log(trace, "[%d] G1-Post Thread: %p Object: %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue());
+ log(trace, "[%d] G1-Post Thread: %p Field: %p\n", gcCycle, thread.rawValue(), oop.rawValue());
+ }
+ Pointer writtenValue = Word.objectToTrackedPointer(fixedValue);
+ // The result of the xor reveals whether the installed pointer crosses heap regions.
+ // In case it does the write barrier has to be issued.
+ final int logOfHeapRegionGrainBytes = logOfHeapRegionGrainBytes();
+ UnsignedWord xorResult = (oop.xor(writtenValue)).unsignedShiftRight(logOfHeapRegionGrainBytes);
+
+ counters.g1AttemptedPostWriteBarrierCounter.inc();
+ if (probability(FREQUENT_PROBABILITY, xorResult.notEqual(0))) {
+ counters.g1EffectiveAfterXORPostWriteBarrierCounter.inc();
+ // If the written value is not null continue with the barrier addition.
+ if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) {
+ // Calculate the address of the card to be enqueued to the
+ // thread local card queue.
+ Word cardAddress = cardTableAddress().add(oop.unsignedShiftRight(cardTableShift()));
+
+ byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION);
+ counters.g1EffectiveAfterNullPostWriteBarrierCounter.inc();
+
+ // If the card is already dirty, (hence already enqueued) skip the insertion.
+ if (probability(NOT_FREQUENT_PROBABILITY, cardByte != youngCardValue())) {
+ MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION);
+ byte cardByteReload = cardAddress.readByte(0, GC_CARD_LOCATION);
+ if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue())) {
+ log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), WordFactory.unsigned((int) cardByte).rawValue());
+ cardAddress.writeByte(0, dirtyCardValue(), GC_CARD_LOCATION);
+ counters.g1ExecutedPostWriteBarrierCounter.inc();
+
+ // If the thread local card queue is full, issue a native call which will
+ // initialize a new one and add the card entry.
+ Word indexValue = thread.readWord(cardQueueIndexOffset(), CARD_QUEUE_INDEX_LOCATION);
+ if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) {
+ Word bufferAddress = thread.readWord(cardQueueBufferOffset(), CARD_QUEUE_BUFFER_LOCATION);
+ Word nextIndex = indexValue.subtract(wordSize());
+ Word logAddress = bufferAddress.add(nextIndex);
+ Word indexAddress = thread.add(cardQueueIndexOffset());
+ // Log the object to be scanned as well as update
+ // the card queue's next index.
+ logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION);
+ indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION);
+ } else {
+ g1PostBarrierStub(cardAddress);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Snippet
+ public void g1ArrayRangePreWriteBarrier(Address address, int length, @ConstantParameter int elementStride) {
+ Word thread = getThread();
+ byte markingValue = thread.readByte(satbQueueMarkingOffset(), SATB_QUEUE_MARKING_LOCATION);
+ // If the concurrent marker is not enabled or the vector length is zero, return.
+ if (probability(FREQUENT_PROBABILITY, markingValue == (byte) 0 || length == 0)) {
+ return;
+ }
+
+ Word bufferAddress = thread.readWord(satbQueueBufferOffset(), SATB_QUEUE_BUFFER_LOCATION);
+ Word indexAddress = thread.add(satbQueueIndexOffset());
+ long indexValue = indexAddress.readWord(0, SATB_QUEUE_INDEX_LOCATION).rawValue();
+ int scale = objectArrayIndexScale();
+ Word start = getPointerToFirstArrayElement(address, length, elementStride);
+
+ for (int i = 0; i < length; i++) {
+ Word arrElemPtr = start.add(i * scale);
+ Object previousObject = arrElemPtr.readObject(0, BarrierType.NONE);
+ verifyOop(previousObject);
+ if (probability(FREQUENT_PROBABILITY, previousObject != null)) {
+ if (probability(FREQUENT_PROBABILITY, indexValue != 0)) {
+ indexValue = indexValue - wordSize();
+ Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue));
+ // Log the object to be marked as well as update the SATB's buffer next index.
+ Word previousOop = Word.objectToTrackedPointer(previousObject);
+ logAddress.writeWord(0, previousOop, GC_LOG_LOCATION);
+ indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION);
+ } else {
+ g1PreBarrierStub(previousObject);
+ }
+ }
+ }
+ }
+
+ @Snippet
+ public void g1ArrayRangePostWriteBarrier(Address address, int length, @ConstantParameter int elementStride) {
+ if (probability(NOT_FREQUENT_PROBABILITY, length == 0)) {
+ return;
+ }
+
+ Word thread = getThread();
+ Word bufferAddress = thread.readWord(cardQueueBufferOffset(), CARD_QUEUE_BUFFER_LOCATION);
+ Word indexAddress = thread.add(cardQueueIndexOffset());
+ long indexValue = thread.readWord(cardQueueIndexOffset(), CARD_QUEUE_INDEX_LOCATION).rawValue();
+
+ int cardShift = cardTableShift();
+ Word cardStart = cardTableAddress();
+ Word start = cardStart.add(getPointerToFirstArrayElement(address, length, elementStride).unsignedShiftRight(cardShift));
+ Word end = cardStart.add(getPointerToLastArrayElement(address, length, elementStride).unsignedShiftRight(cardShift));
+
+ Word cur = start;
+ do {
+ byte cardByte = cur.readByte(0, GC_CARD_LOCATION);
+ // If the card is already dirty, (hence already enqueued) skip the insertion.
+ if (probability(NOT_FREQUENT_PROBABILITY, cardByte != youngCardValue())) {
+ MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION);
+ byte cardByteReload = cur.readByte(0, GC_CARD_LOCATION);
+ if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue())) {
+ cur.writeByte(0, dirtyCardValue(), GC_CARD_LOCATION);
+ // If the thread local card queue is full, issue a native call which will
+ // initialize a new one and add the card entry.
+ if (probability(FREQUENT_PROBABILITY, indexValue != 0)) {
+ indexValue = indexValue - wordSize();
+ Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue));
+ // Log the object to be scanned as well as update
+ // the card queue's next index.
+ logAddress.writeWord(0, cur, GC_LOG_LOCATION);
+ indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION);
+ } else {
+ g1PostBarrierStub(cur);
+ }
+ }
+ }
+ cur = cur.add(1);
+ } while (cur.belowOrEqual(end));
+ }
+
+ protected abstract Word getThread();
+
+ protected abstract int wordSize();
+
+ protected abstract int objectArrayIndexScale();
+
+ protected abstract int satbQueueMarkingOffset();
+
+ protected abstract int satbQueueBufferOffset();
+
+ protected abstract int satbQueueIndexOffset();
+
+ protected abstract int cardQueueBufferOffset();
+
+ protected abstract int cardQueueIndexOffset();
+
+ protected abstract byte dirtyCardValue();
+
+ protected abstract byte youngCardValue();
+
+ protected abstract Word cardTableAddress();
+
+ protected abstract int cardTableShift();
+
+ protected abstract int logOfHeapRegionGrainBytes();
+
+ protected abstract ForeignCallDescriptor preWriteBarrierCallDescriptor();
+
+ protected abstract ForeignCallDescriptor postWriteBarrierCallDescriptor();
+
+ // the data below is only needed for the verification logic
+ protected abstract boolean verifyOops();
+
+ protected abstract boolean verifyBarrier();
+
+ protected abstract long gcTotalCollectionsAddress();
+
+ protected abstract ForeignCallDescriptor verifyOopCallDescriptor();
+
+ protected abstract ForeignCallDescriptor validateObjectCallDescriptor();
+
+ protected abstract ForeignCallDescriptor printfCallDescriptor();
+
+ private boolean isTracingActive(int traceStartCycle) {
+ return traceStartCycle > 0 && ((Pointer) WordFactory.pointer(gcTotalCollectionsAddress())).readLong(0) > traceStartCycle;
+ }
+
+ private void log(boolean enabled, String format, long value1, long value2, long value3) {
+ if (enabled) {
+ printf(printfCallDescriptor(), CStringConstant.cstring(format), value1, value2, value3);
+ }
+ }
+
+ /**
+ * Validation helper method which performs sanity checks on write operations. The addresses of
+ * both the object and the value being written are checked in order to determine if they reside
+ * in a valid heap region. If an object is stale, an invalid access is performed in order to
+ * prematurely crash the VM and debug the stack trace of the faulty method.
+ */
+ private void validateObject(Object parent, Object child) {
+ if (verifyOops() && child != null) {
+ Word parentWord = Word.objectToTrackedPointer(parent);
+ Word childWord = Word.objectToTrackedPointer(child);
+ boolean success = validateOop(validateObjectCallDescriptor(), parentWord, childWord);
+ AssertionNode.assertion(false, success, "Verification ERROR, Parent: %p Child: %p\n", parentWord.rawValue(), childWord.rawValue());
+ }
+ }
+
+ private void verifyOop(Object object) {
+ if (verifyOops()) {
+ verifyOopStub(verifyOopCallDescriptor(), object);
+ }
+ }
+
+ private void g1PreBarrierStub(Object previousObject) {
+ g1PreBarrierStub(preWriteBarrierCallDescriptor(), previousObject);
+ }
+
+ private void g1PostBarrierStub(Word cardAddress) {
+ g1PostBarrierStub(postWriteBarrierCallDescriptor(), cardAddress);
+ }
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native boolean validateOop(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word parent, Word object);
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native void g1PreBarrierStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object);
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native void g1PostBarrierStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word card);
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ private static native void printf(@ConstantNodeParameter ForeignCallDescriptor logPrintf, Word format, long v1, long v2, long v3);
+
+ public abstract static class G1WriteBarrierLowerer {
+ private final Counters counters;
+
+ public G1WriteBarrierLowerer(Group.Factory factory) {
+ this.counters = new Counters(factory);
+ }
+
+ public void lower(AbstractTemplates templates, SnippetInfo snippet, G1PreWriteBarrier barrier, LoweringTool tool) {
+ Arguments args = new Arguments(snippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ AddressNode address = barrier.getAddress();
+ args.add("address", address);
+ if (address instanceof OffsetAddressNode) {
+ args.add("object", ((OffsetAddressNode) address).getBase());
+ } else {
+ args.add("object", null);
+ }
+
+ ValueNode expected = barrier.getExpectedObject();
+ if (expected != null && expected.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) {
+ expected = uncompress(expected);
+ }
+ args.add("expectedObject", expected);
+
+ args.addConst("doLoad", barrier.doLoad());
+ args.addConst("nullCheck", barrier.getNullCheck());
+ args.addConst("traceStartCycle", traceStartCycle(barrier.graph()));
+ args.addConst("counters", counters);
+
+ templates.template(barrier, args).instantiate(templates.getProviders().getMetaAccess(), barrier, SnippetTemplate.DEFAULT_REPLACER, args);
+ }
+
+ public void lower(AbstractTemplates templates, SnippetInfo snippet, G1ReferentFieldReadBarrier barrier, LoweringTool tool) {
+ Arguments args = new Arguments(snippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ AddressNode address = barrier.getAddress();
+ args.add("address", address);
+ if (address instanceof OffsetAddressNode) {
+ args.add("object", ((OffsetAddressNode) address).getBase());
+ } else {
+ args.add("object", null);
+ }
+
+ ValueNode expected = barrier.getExpectedObject();
+ if (expected != null && expected.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) {
+ expected = uncompress(expected);
+ }
+
+ args.add("expectedObject", expected);
+ args.addConst("doLoad", barrier.doLoad());
+ args.addConst("nullCheck", false);
+ args.addConst("traceStartCycle", traceStartCycle(barrier.graph()));
+ args.addConst("counters", counters);
+
+ templates.template(barrier, args).instantiate(templates.getProviders().getMetaAccess(), barrier, SnippetTemplate.DEFAULT_REPLACER, args);
+ }
+
+ public void lower(AbstractTemplates templates, SnippetInfo snippet, G1PostWriteBarrier barrier, LoweringTool tool) {
+ if (barrier.alwaysNull()) {
+ barrier.graph().removeFixed(barrier);
+ return;
+ }
+
+ Arguments args = new Arguments(snippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ AddressNode address = barrier.getAddress();
+ args.add("address", address);
+ if (address instanceof OffsetAddressNode) {
+ args.add("object", ((OffsetAddressNode) address).getBase());
+ } else {
+ assert barrier.usePrecise() : "found imprecise barrier that's not an object access " + barrier;
+ args.add("object", null);
+ }
+
+ ValueNode value = barrier.getValue();
+ if (value.stamp(NodeView.DEFAULT) instanceof NarrowOopStamp) {
+ value = uncompress(value);
+ }
+ args.add("value", value);
+
+ args.addConst("usePrecise", barrier.usePrecise());
+ args.addConst("traceStartCycle", traceStartCycle(barrier.graph()));
+ args.addConst("counters", counters);
+
+ templates.template(barrier, args).instantiate(templates.getProviders().getMetaAccess(), barrier, SnippetTemplate.DEFAULT_REPLACER, args);
+ }
+
+ public void lower(AbstractTemplates templates, SnippetInfo snippet, G1ArrayRangePreWriteBarrier barrier, LoweringTool tool) {
+ Arguments args = new Arguments(snippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ args.add("address", barrier.getAddress());
+ args.add("length", barrier.getLength());
+ args.addConst("elementStride", barrier.getElementStride());
+
+ templates.template(barrier, args).instantiate(templates.getProviders().getMetaAccess(), barrier, SnippetTemplate.DEFAULT_REPLACER, args);
+ }
+
+ public void lower(AbstractTemplates templates, SnippetInfo snippet, G1ArrayRangePostWriteBarrier barrier, LoweringTool tool) {
+ Arguments args = new Arguments(snippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ args.add("address", barrier.getAddress());
+ args.add("length", barrier.getLength());
+ args.addConst("elementStride", barrier.getElementStride());
+
+ templates.template(barrier, args).instantiate(templates.getProviders().getMetaAccess(), barrier, SnippetTemplate.DEFAULT_REPLACER, args);
+ }
+
+ private static int traceStartCycle(StructuredGraph graph) {
+ return GraalOptions.GCDebugStartCycle.getValue(graph.getOptions());
+ }
+
+ protected abstract ValueNode uncompress(ValueNode value);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/SerialWriteBarrierSnippets.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.gc;
+
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
+import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
+import org.graalvm.compiler.nodes.gc.SerialArrayRangeWriteBarrier;
+import org.graalvm.compiler.nodes.gc.SerialWriteBarrier;
+import org.graalvm.compiler.nodes.memory.address.AddressNode.Address;
+import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.replacements.SnippetCounter;
+import org.graalvm.compiler.replacements.SnippetCounter.Group;
+import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
+import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
+import org.graalvm.compiler.replacements.Snippets;
+import org.graalvm.compiler.replacements.nodes.AssertionNode;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.Pointer;
+
+public abstract class SerialWriteBarrierSnippets extends WriteBarrierSnippets implements Snippets {
+ static class Counters {
+ Counters(SnippetCounter.Group.Factory factory) {
+ Group countersWriteBarriers = factory.createSnippetCounterGroup("Serial WriteBarriers");
+ serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers");
+ }
+
+ final SnippetCounter serialWriteBarrierCounter;
+ }
+
+ @Snippet
+ public void serialImpreciseWriteBarrier(Object object, @ConstantParameter Counters counters, @ConstantParameter boolean verifyOnly) {
+ if (verifyBarrier()) {
+ verifyNotArray(object);
+ }
+ serialWriteBarrier(Word.objectToTrackedPointer(object), counters, verifyOnly);
+ }
+
+ @Snippet
+ public void serialPreciseWriteBarrier(Address address, @ConstantParameter Counters counters, @ConstantParameter boolean verifyOnly) {
+ serialWriteBarrier(Word.fromAddress(address), counters, verifyOnly);
+ }
+
+ @Snippet
+ public void serialArrayRangeWriteBarrier(Address address, int length, @ConstantParameter int elementStride) {
+ if (probability(NOT_FREQUENT_PROBABILITY, length == 0)) {
+ return;
+ }
+
+ int cardShift = cardTableShift();
+ Word cardTableAddress = cardTableAddress();
+ Word start = cardTableAddress.add(getPointerToFirstArrayElement(address, length, elementStride).unsignedShiftRight(cardShift));
+ Word end = cardTableAddress.add(getPointerToLastArrayElement(address, length, elementStride).unsignedShiftRight(cardShift));
+
+ Word cur = start;
+ do {
+ cur.writeByte(0, dirtyCardValue(), GC_CARD_LOCATION);
+ cur = cur.add(1);
+ } while (cur.belowOrEqual(end));
+ }
+
+ private void serialWriteBarrier(Pointer ptr, Counters counters, boolean verifyOnly) {
+ if (!verifyOnly) {
+ counters.serialWriteBarrierCounter.inc();
+ }
+
+ Word base = cardTableAddress().add(ptr.unsignedShiftRight(cardTableShift()));
+ if (verifyOnly) {
+ byte cardValue = base.readByte(0, GC_CARD_LOCATION);
+ AssertionNode.assertion(false, cardValue == dirtyCardValue(), "card must be dirty");
+ } else {
+ base.writeByte(0, dirtyCardValue(), GC_CARD_LOCATION);
+ }
+ }
+
+ protected abstract Word cardTableAddress();
+
+ protected abstract int cardTableShift();
+
+ protected abstract boolean verifyBarrier();
+
+ protected abstract byte dirtyCardValue();
+
+ public static class SerialWriteBarrierLowerer {
+ private final Counters counters;
+
+ public SerialWriteBarrierLowerer(Group.Factory factory) {
+ this.counters = new Counters(factory);
+ }
+
+ public void lower(AbstractTemplates templates, SnippetInfo preciseSnippet, SnippetInfo impreciseSnippet, SerialWriteBarrier barrier, LoweringTool tool) {
+ Arguments args;
+ if (barrier.usePrecise()) {
+ args = new Arguments(preciseSnippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ args.add("address", barrier.getAddress());
+ } else {
+ args = new Arguments(impreciseSnippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ OffsetAddressNode address = (OffsetAddressNode) barrier.getAddress();
+ args.add("object", address.getBase());
+ }
+ args.addConst("counters", counters);
+ args.addConst("verifyOnly", barrier.getVerifyOnly());
+
+ templates.template(barrier, args).instantiate(templates.getProviders().getMetaAccess(), barrier, DEFAULT_REPLACER, args);
+ }
+
+ public void lower(AbstractTemplates templates, SnippetInfo snippet, SerialArrayRangeWriteBarrier barrier, LoweringTool tool) {
+ Arguments args = new Arguments(snippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
+ args.add("address", barrier.getAddress());
+ args.add("length", barrier.getLength());
+ args.addConst("elementStride", barrier.getElementStride());
+
+ templates.template(barrier, args).instantiate(templates.getProviders().getMetaAccess(), barrier, DEFAULT_REPLACER, args);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/WriteBarrierSnippets.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.replacements.gc;
+
+import org.graalvm.compiler.nodes.NamedLocationIdentity;
+import org.graalvm.compiler.nodes.PiNode;
+import org.graalvm.compiler.nodes.SnippetAnchorNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode.Address;
+import org.graalvm.compiler.replacements.nodes.AssertionNode;
+import org.graalvm.compiler.word.Word;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
+
+public abstract class WriteBarrierSnippets {
+ public static final LocationIdentity GC_CARD_LOCATION = NamedLocationIdentity.mutable("GC-Card");
+
+ protected static void verifyNotArray(Object object) {
+ if (object != null) {
+ // Manually build the null check and cast because we're in snippet that's lowered late.
+ AssertionNode.assertion(false, !PiNode.piCastNonNull(object, SnippetAnchorNode.anchor()).getClass().isArray(), "imprecise card mark used with array");
+ }
+ }
+
+ protected static Word getPointerToFirstArrayElement(Address address, int length, int elementStride) {
+ long result = Word.fromAddress(address).rawValue();
+ if (elementStride < 0) {
+ // the address points to the place after the last array element
+ result = result + elementStride * length;
+ }
+ return WordFactory.unsigned(result);
+ }
+
+ protected static Word getPointerToLastArrayElement(Address address, int length, int elementStride) {
+ long result = Word.fromAddress(address).rawValue();
+ if (elementStride < 0) {
+ // the address points to the place after the last array element
+ result = result + elementStride;
+ } else {
+ result = result + (length - 1) * elementStride;
+ }
+ return WordFactory.unsigned(result);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/DirectStoreNode.java Wed Jun 26 14:28:47 2019 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package org.graalvm.compiler.replacements.nodes;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
-
-import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.core.common.type.StampFactory;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.FixedWithNextNode;
-import org.graalvm.compiler.nodes.StateSplit;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.RawStoreNode;
-import org.graalvm.compiler.nodes.spi.LIRLowerable;
-import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.Value;
-
-/**
- * A special purpose store node that differs from {@link RawStoreNode} in that it is not a
- * {@link StateSplit} and takes a computed address instead of an object.
- */
-@NodeInfo(cycles = CYCLES_2, size = SIZE_1)
-public final class DirectStoreNode extends FixedWithNextNode implements LIRLowerable {
-
- public static final NodeClass<DirectStoreNode> TYPE = NodeClass.create(DirectStoreNode.class);
- @Input protected ValueNode address;
- @Input protected ValueNode value;
- protected final JavaKind kind;
-
- public DirectStoreNode(ValueNode address, ValueNode value, JavaKind kind) {
- super(TYPE, StampFactory.forVoid());
- this.address = address;
- this.value = value;
- this.kind = kind;
- }
-
- @Override
- public void generate(NodeLIRBuilderTool gen) {
- Value v = gen.operand(value);
- LIRKind lirKind = LIRKind.fromJavaKind(gen.getLIRGeneratorTool().target().arch, kind);
- gen.getLIRGeneratorTool().getArithmetic().emitStore(lirKind, gen.operand(address), v, null);
- }
-
- public ValueNode getAddress() {
- return address;
- }
-
- public ValueNode getValue() {
- return value;
- }
-
- @NodeIntrinsic
- public static native void storeBoolean(long address, boolean value, @ConstantNodeParameter JavaKind kind);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -49,6 +49,7 @@
import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
@@ -57,7 +58,6 @@
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.RemoveValueProxyPhase;
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
@@ -160,7 +160,7 @@
*/
@SuppressWarnings("try")
protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) {
- final PhaseContext c = new PhaseContext(tool.getProviders());
+ final CoreProviders c = tool.getProviders();
if (!graph().hasValueProxies()) {
new RemoveValueProxyPhase().apply(replacementGraph);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java Fri Jun 28 14:36:42 2019 +0530
@@ -206,7 +206,8 @@
StampPair returnStamp, ValueNode[] arguments) {
ValueNode methodHandleNode = getReceiver(arguments);
if (methodHandleNode.isConstant()) {
- return getTargetInvokeNode(adder, intrinsicMethod, bci, returnStamp, arguments, methodHandleAccess.resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), true), original);
+ return getTargetInvokeNode(adder, intrinsicMethod, methodHandleAccess, bci, returnStamp, arguments, methodHandleAccess.resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), true),
+ original);
}
return null;
}
@@ -227,7 +228,7 @@
StampPair returnStamp, ValueNode[] arguments) {
ValueNode memberNameNode = getMemberName(arguments);
if (memberNameNode.isConstant()) {
- return getTargetInvokeNode(adder, intrinsicMethod, bci, returnStamp, arguments, methodHandleAccess.resolveLinkToTarget(memberNameNode.asJavaConstant()), original);
+ return getTargetInvokeNode(adder, intrinsicMethod, methodHandleAccess, bci, returnStamp, arguments, methodHandleAccess.resolveLinkToTarget(memberNameNode.asJavaConstant()), original);
}
return null;
}
@@ -241,9 +242,10 @@
*
* @return invoke node for the member name target
*/
- private static InvokeNode getTargetInvokeNode(GraphAdder adder, IntrinsicMethod intrinsicMethod, int bci, StampPair returnStamp, ValueNode[] originalArguments, ResolvedJavaMethod target,
+ private static InvokeNode getTargetInvokeNode(GraphAdder adder, IntrinsicMethod intrinsicMethod, MethodHandleAccessProvider methodHandleAccess, int bci, StampPair returnStamp,
+ ValueNode[] originalArguments, ResolvedJavaMethod target,
ResolvedJavaMethod original) {
- if (target == null) {
+ if (target == null || !isConsistentInfo(methodHandleAccess, original, target)) {
return null;
}
@@ -390,4 +392,84 @@
return new InvokeNode(callTarget, bci);
}
}
+
+ /**
+ * Checks basic type consistency of low level method handle intrinsics.
+ *
+ * @param original declared method
+ * @param target resolved method
+ * @return true if original is type consistent with target
+ */
+ private static boolean isConsistentInfo(MethodHandleAccessProvider methodHandleAccess, ResolvedJavaMethod original, ResolvedJavaMethod target) {
+ IntrinsicMethod originalIntrinsicMethod = methodHandleAccess.lookupMethodHandleIntrinsic(original);
+ assert originalIntrinsicMethod == IntrinsicMethod.INVOKE_BASIC ||
+ originalIntrinsicMethod == IntrinsicMethod.LINK_TO_STATIC ||
+ originalIntrinsicMethod == IntrinsicMethod.LINK_TO_SPECIAL ||
+ originalIntrinsicMethod == IntrinsicMethod.LINK_TO_VIRTUAL ||
+ originalIntrinsicMethod == IntrinsicMethod.LINK_TO_INTERFACE;
+ IntrinsicMethod targetIntrinsicMethod = methodHandleAccess.lookupMethodHandleIntrinsic(target);
+ Signature originalSignature = original.getSignature();
+ Signature targetSignature = target.getSignature();
+
+ boolean invokeThroughMHIntrinsic = originalIntrinsicMethod != null && targetIntrinsicMethod == null;
+ if (!invokeThroughMHIntrinsic) {
+ return (original.getName().equals(target.getName())) && (originalSignature.equals(targetSignature));
+ }
+
+ // Linkers have appendix argument which is not passed to callee.
+ int hasAppendix = (originalIntrinsicMethod == IntrinsicMethod.LINK_TO_STATIC ||
+ originalIntrinsicMethod == IntrinsicMethod.LINK_TO_SPECIAL ||
+ originalIntrinsicMethod == IntrinsicMethod.LINK_TO_VIRTUAL ||
+ originalIntrinsicMethod == IntrinsicMethod.LINK_TO_INTERFACE) ? 1 : 0;
+ if (originalSignature.getParameterCount(original.hasReceiver()) != (targetSignature.getParameterCount(target.hasReceiver()) + hasAppendix)) {
+ return false; // parameter count mismatch
+ }
+ int senderBase = 0;
+ int receiverBase = 0;
+ switch (originalIntrinsicMethod) {
+ case LINK_TO_VIRTUAL:
+ case LINK_TO_INTERFACE:
+ case LINK_TO_SPECIAL: {
+ if (target.isStatic()) {
+ return false;
+ }
+ if (originalSignature.getParameterKind(0).isPrimitive()) {
+ return false; // receiver should be an oop
+ }
+ senderBase = 1; // skip receiver
+ break;
+ }
+ case LINK_TO_STATIC: {
+ if (target.hasReceiver()) {
+ return false;
+ }
+ break;
+ }
+ case INVOKE_BASIC: {
+ if (target.isStatic()) {
+ if (targetSignature.getParameterKind(0).isPrimitive()) {
+ return false; // receiver should be an oop
+ }
+ receiverBase = 1; // skip receiver
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ assert (targetSignature.getParameterCount(false) - receiverBase) == (originalSignature.getParameterCount(false) - senderBase - hasAppendix) : "argument count mismatch";
+ int argCount = targetSignature.getParameterCount(false) - receiverBase;
+ for (int i = 0; i < argCount; i++) {
+ if (originalSignature.getParameterKind(senderBase + i).getStackKind() != targetSignature.getParameterKind(receiverBase + i).getStackKind()) {
+ return false;
+ }
+ }
+ // Only check the return type if the symbolic info has non-void return type.
+ // I.e. the return value of the resolved method can be dropped.
+ if (originalSignature.getReturnKind() != JavaKind.Void &&
+ originalSignature.getReturnKind().getStackKind() != targetSignature.getReturnKind().getStackKind()) {
+ return false;
+ }
+ return true; // no mismatch found
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/BufferUtil.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.serviceprovider;
+
+import java.nio.Buffer;
+
+/**
+ * Covariant return types for some methods in the {@code java.nio.Buffer} were
+ * <a href="https://bugs.openjdk.java.net/browse/JDK-4774077">introduced in JDK 9</a>.
+ *
+ * If calls to these methods are compiled with javac from JDK 9+ using {@code -target 8 -source 8}
+ * then the call sites will invoke the covariant methods in the subclass. For example:
+ *
+ * <pre>
+ * static void reset(ByteBuffer buf) {
+ * buf.reset();
+ * }
+ * </pre>
+ *
+ * will result in:
+ *
+ * <pre>
+ * 0: aload_0
+ * 1: invokevirtual #7 // Method java/nio/ByteBuffer.reset:()Ljava/nio/ByteBuffer;
+ * 4: pop
+ * 5: return
+ * </pre>
+ *
+ * This will result in a {@link NoSuchMethodError} when run on JDK 8. The workaround for this is to
+ * {@linkplain #asBaseBuffer(Buffer) coerce} the receiver for calls to the covariant methods to
+ * {@link Buffer}.
+ */
+public final class BufferUtil {
+
+ /**
+ * Coerces {@code obj} to be of type {@link Buffer}. This is required instead of a cast as
+ * {@code org.graalvm.compiler.core.test.VerifyBufferUsage} is based on Graal graphs which will
+ * have had redundant casts eliminated by the bytecode parser.
+ */
+ public static Buffer asBaseBuffer(Buffer obj) {
+ return obj;
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java Fri Jun 28 14:36:42 2019 +0530
@@ -89,7 +89,15 @@
synchronized (servicesCache) {
ArrayList<S> providersList = new ArrayList<>();
for (S provider : providers) {
- providersList.add(provider);
+ /*
+ * When building libgraal, we want providers that comes from the Graal community
+ * and enterprise modules but not those available on the native-image class
+ * path.
+ */
+ Module module = provider.getClass().getModule();
+ if (module.isNamed()) {
+ providersList.add(provider);
+ }
}
providers = providersList;
servicesCache.put(service, providersList);
@@ -101,7 +109,7 @@
}
protected static <S> Iterable<S> load0(Class<S> service) {
- Iterable<S> iterable = ServiceLoader.load(service, GraalServices.class.getClassLoader());
+ Iterable<S> iterable = ServiceLoader.load(service);
return new Iterable<>() {
@Override
public Iterator<S> iterator() {
@@ -136,7 +144,9 @@
* @param other all JVMCI packages will be opened to the module defining this class
*/
static void openJVMCITo(Class<?> other) {
- if (IS_IN_NATIVE_IMAGE) return;
+ if (IS_IN_NATIVE_IMAGE) {
+ return;
+ }
Module jvmciModule = JVMCI_MODULE;
Module otherModule = other.getModule();
@@ -526,6 +536,6 @@
* was produced as a result of a call to a {@code valueOf} method.
*/
public static void markVirtualObjectAsAutoBox(VirtualObject virtualObject) {
- virtualObject.setIsAutoBox(true);
+ virtualObject.setIsAutoBox(true);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JavaVersionUtil.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JavaVersionUtil.java Fri Jun 28 14:36:42 2019 +0530
@@ -43,17 +43,7 @@
* The integer value corresponding to the value of the {@code java.specification.version} system
* property after any leading {@code "1."} has been stripped.
*/
- public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion();
-
- /**
- * Determines if the Java runtime is version 8 or earlier.
- */
- public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8;
-
- /**
- * Determines if the Java runtime is version 11 or earlier.
- */
- public static final boolean Java11OrEarlier = JAVA_SPECIFICATION_VERSION <= 11;
+ public static final int JAVA_SPEC = getJavaSpecificationVersion();
private JavaVersionUtil() {
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/ExportingClassLoader.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/ExportingClassLoader.java Fri Jun 28 14:36:42 2019 +0530
@@ -24,20 +24,22 @@
package org.graalvm.compiler.test;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
+
/**
* A class loader that exports all packages in the module defining the class loader to all classes
* in the unnamed module associated with the loader.
*/
public class ExportingClassLoader extends ClassLoader {
public ExportingClassLoader() {
- if (!GraalTest.Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
JLModule.fromClass(getClass()).exportAllPackagesTo(JLModule.getUnnamedModuleFor(this));
}
}
public ExportingClassLoader(ClassLoader parent) {
super(parent);
- if (!GraalTest.Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC > 8) {
JLModule.fromClass(getClass()).exportAllPackagesTo(JLModule.getUnnamedModuleFor(this));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -44,7 +44,6 @@
import org.graalvm.compiler.debug.GlobalMetrics;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.GraalServices;
-import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.AssumptionViolatedException;
@@ -73,9 +72,6 @@
}
}
- public static final boolean Java8OrEarlier = JavaVersionUtil.Java8OrEarlier;
- public static final boolean Java11OrEarlier = JavaVersionUtil.Java11OrEarlier;
-
protected Method getMethod(String methodName) {
return getMethod(getClass(), methodName);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/JLModule.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/JLModule.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,6 +28,8 @@
import java.lang.reflect.Method;
import java.util.Set;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
+
/**
* Facade for the {@code java.lang.Module} class introduced in JDK9 that allows tests to be
* developed against JDK8 but use module logic if deployed on JDK9.
@@ -35,7 +37,7 @@
public class JLModule {
static {
- if (GraalTest.Java8OrEarlier) {
+ if (JavaVersionUtil.JAVA_SPEC <= 8) {
throw new AssertionError("Use of " + JLModule.class + " only allowed if " + GraalTest.class.getName() + ".JDK8OrEarlier is false");
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Fri Jun 28 14:36:42 2019 +0530
@@ -249,7 +249,7 @@
return new Subprocess(command, process.waitFor(), output);
}
- private static final boolean isJava8OrEarlier = JavaVersionUtil.Java8OrEarlier;
+ private static final boolean isJava8OrEarlier = JavaVersionUtil.JAVA_SPEC <= 8;
private static boolean hasArg(String optionName) {
if (optionName.equals("-cp") || optionName.equals("-classpath")) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EarlyReadEliminationPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EarlyReadEliminationPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -29,10 +29,10 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
-public class EarlyReadEliminationPhase extends EffectsPhase<PhaseContext> {
+public class EarlyReadEliminationPhase extends EffectsPhase<CoreProviders> {
private final boolean considerGuards;
@@ -47,14 +47,14 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
if (VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue(graph.getOptions()))) {
runAnalysis(graph, context);
}
}
@Override
- protected Closure<?> createEffectsClosure(PhaseContext context, ScheduleResult schedule, ControlFlowGraph cfg) {
+ protected Closure<?> createEffectsClosure(CoreProviders context, ScheduleResult schedule, ControlFlowGraph cfg) {
assert schedule == null;
return new ReadEliminationClosure(cfg, considerGuards);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -31,19 +31,18 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.graph.spi.Simplifiable;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
-public abstract class EffectsPhase<PhaseContextT extends PhaseContext> extends BasePhase<PhaseContextT> {
+public abstract class EffectsPhase<CoreProvidersT extends CoreProviders> extends BasePhase<CoreProvidersT> {
public abstract static class Closure<T> extends ReentrantBlockIterator.BlockIteratorClosure<T> {
@@ -69,12 +68,12 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContextT context) {
+ protected void run(StructuredGraph graph, CoreProvidersT context) {
runAnalysis(graph, context);
}
@SuppressWarnings("try")
- public boolean runAnalysis(StructuredGraph graph, PhaseContextT context) {
+ public boolean runAnalysis(StructuredGraph graph, CoreProvidersT context) {
boolean changed = false;
CompilationAlarm compilationAlarm = CompilationAlarm.current();
DebugContext debug = graph.getDebug();
@@ -99,21 +98,15 @@
EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener();
try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
closure.applyEffects();
- }
- if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) {
- debug.dump(DebugContext.VERBOSE_LEVEL, graph, "%s iteration", getName());
+ if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) {
+ debug.dump(DebugContext.VERBOSE_LEVEL, graph, "%s iteration", getName());
+ }
+
+ new DeadCodeEliminationPhase(Required).apply(graph);
}
- new DeadCodeEliminationPhase(Required).apply(graph);
-
- EconomicSet<Node> changedNodes = listener.getNodes();
- for (Node node : graph.getNodes()) {
- if (node instanceof Simplifiable) {
- changedNodes.add(node);
- }
- }
- postIteration(graph, context, changedNodes);
+ postIteration(graph, context, listener.getNodes());
}
if (closure.hasChanged()) {
@@ -129,11 +122,11 @@
return changed;
}
- protected void postIteration(final StructuredGraph graph, final PhaseContextT context, EconomicSet<Node> changedNodes) {
+ protected void postIteration(final StructuredGraph graph, final CoreProvidersT context, EconomicSet<Node> changedNodes) {
if (canonicalizer != null) {
canonicalizer.applyIncremental(graph, context, changedNodes);
}
}
- protected abstract Closure<?> createEffectsClosure(PhaseContextT context, ScheduleResult schedule, ControlFlowGraph cfg);
+ protected abstract Closure<?> createEffectsClosure(CoreProvidersT context, ScheduleResult schedule, ControlFlowGraph cfg);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
import java.util.ArrayList;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.ControlSinkNode;
@@ -196,11 +197,14 @@
public void replaceWithSink(FixedWithNextNode node, ControlSinkNode sink) {
add("kill if branch", new Effect() {
+ @SuppressWarnings("try")
@Override
public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
- graph.addWithoutUnique(sink);
- node.replaceAtPredecessor(sink);
- GraphUtil.killCFG(node);
+ try (DebugCloseable position = graph.withNodeSourcePosition(node)) {
+ graph.addWithoutUnique(sink);
+ node.replaceAtPredecessor(sink);
+ GraphUtil.killCFG(node);
+ }
}
@Override
@@ -221,33 +225,36 @@
* @param insertBefore
*
*/
+ @SuppressWarnings("try")
public void replaceAtUsages(ValueNode node, ValueNode replacement, FixedNode insertBefore) {
assert node != null && replacement != null : node + " " + replacement;
assert !node.hasUsages() || node.stamp(NodeView.DEFAULT).isCompatible(replacement.stamp(NodeView.DEFAULT)) : "Replacement node stamp not compatible " + node.stamp(NodeView.DEFAULT) + " vs " +
replacement.stamp(NodeView.DEFAULT);
add("replace at usages", (graph, obsoleteNodes) -> {
- assert node.isAlive();
- ValueNode replacementNode = graph.addOrUniqueWithInputs(replacement);
- assert replacementNode.isAlive();
- assert insertBefore != null;
- if (replacementNode instanceof FixedWithNextNode && ((FixedWithNextNode) replacementNode).next() == null) {
- graph.addBeforeFixed(insertBefore, (FixedWithNextNode) replacementNode);
+ try (DebugCloseable position = graph.withNodeSourcePosition(node)) {
+ assert node.isAlive();
+ ValueNode replacementNode = graph.addOrUniqueWithInputs(replacement);
+ assert replacementNode.isAlive();
+ assert insertBefore != null;
+ if (replacementNode instanceof FixedWithNextNode && ((FixedWithNextNode) replacementNode).next() == null) {
+ graph.addBeforeFixed(insertBefore, (FixedWithNextNode) replacementNode);
+ }
+ /*
+ * Keep the (better) stamp information when replacing a node with another one if the
+ * replacement has a less precise stamp than the original node. This can happen for
+ * example in the context of read nodes and unguarded pi nodes where the pi will be
+ * used to improve the stamp information of the read. Such a read might later be
+ * replaced with a read with a less precise stamp.
+ */
+ if (node.hasUsages() && !node.stamp(NodeView.DEFAULT).equals(replacementNode.stamp(NodeView.DEFAULT))) {
+ replacementNode = graph.unique(new PiNode(replacementNode, node.stamp(NodeView.DEFAULT)));
+ }
+ node.replaceAtUsages(replacementNode);
+ if (node instanceof FixedWithNextNode) {
+ GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
+ }
+ obsoleteNodes.add(node);
}
- /*
- * Keep the (better) stamp information when replacing a node with another one if the
- * replacement has a less precise stamp than the original node. This can happen for
- * example in the context of read nodes and unguarded pi nodes where the pi will be used
- * to improve the stamp information of the read. Such a read might later be replaced
- * with a read with a less precise stamp.
- */
- if (node.hasUsages() && !node.stamp(NodeView.DEFAULT).equals(replacementNode.stamp(NodeView.DEFAULT))) {
- replacementNode = graph.unique(new PiNode(replacementNode, node.stamp(NodeView.DEFAULT)));
- }
- node.replaceAtUsages(replacementNode);
- if (node instanceof FixedWithNextNode) {
- GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
- }
- obsoleteNodes.add(node);
});
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Fri Jun 28 14:36:42 2019 +0530
@@ -32,6 +32,7 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
+import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
@@ -39,9 +40,8 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.tiers.PhaseContext;
-public class PartialEscapePhase extends EffectsPhase<PhaseContext> {
+public class PartialEscapePhase extends EffectsPhase<CoreProviders> {
static class Options {
//@formatter:off
@@ -51,24 +51,24 @@
}
private final boolean readElimination;
- private final BasePhase<PhaseContext> cleanupPhase;
+ private final BasePhase<CoreProviders> cleanupPhase;
public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer, OptionValues options) {
this(iterative, Options.OptEarlyReadElimination.getValue(options), canonicalizer, null, options);
}
- public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer, BasePhase<PhaseContext> cleanupPhase, OptionValues options) {
+ public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer, BasePhase<CoreProviders> cleanupPhase, OptionValues options) {
this(iterative, Options.OptEarlyReadElimination.getValue(options), canonicalizer, cleanupPhase, options);
}
- public PartialEscapePhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer, BasePhase<PhaseContext> cleanupPhase, OptionValues options) {
+ public PartialEscapePhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer, BasePhase<CoreProviders> cleanupPhase, OptionValues options) {
super(iterative ? EscapeAnalysisIterations.getValue(options) : 1, canonicalizer);
this.readElimination = readElimination;
this.cleanupPhase = cleanupPhase;
}
@Override
- protected void postIteration(StructuredGraph graph, PhaseContext context, EconomicSet<Node> changedNodes) {
+ protected void postIteration(StructuredGraph graph, CoreProviders context, EconomicSet<Node> changedNodes) {
super.postIteration(graph, context, changedNodes);
if (cleanupPhase != null) {
cleanupPhase.apply(graph, context);
@@ -76,7 +76,7 @@
}
@Override
- protected void run(StructuredGraph graph, PhaseContext context) {
+ protected void run(StructuredGraph graph, CoreProviders context) {
if (VirtualUtil.matches(graph, EscapeAnalyzeOnly.getValue(graph.getOptions()))) {
if (readElimination || graph.hasVirtualizableAllocation()) {
runAnalysis(graph, context);
@@ -85,7 +85,7 @@
}
@Override
- protected Closure<?> createEffectsClosure(PhaseContext context, ScheduleResult schedule, ControlFlowGraph cfg) {
+ protected Closure<?> createEffectsClosure(CoreProviders context, ScheduleResult schedule, ControlFlowGraph cfg) {
for (VirtualObjectNode virtual : cfg.graph.getNodes(VirtualObjectNode.TYPE)) {
virtual.resetObjectId();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java Fri Jun 28 14:36:42 2019 +0530
@@ -38,7 +38,7 @@
*
* @param <G> the type of graph this instance handles
* @param <M> the type of methods this instance handles
- * @since 1.0 a {@link WritableByteChannel} is implemented
+ * @since 19.0 a {@link WritableByteChannel} is implemented
*/
public final class GraphOutput<G, M> implements Closeable, WritableByteChannel {
private final GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?, ?> printer;
@@ -112,7 +112,7 @@
* Checks if the {@link GraphOutput} is open.
*
* @return true if the {@link GraphOutput} is open.
- * @since 1.0
+ * @since 19.0
*/
@Override
public boolean isOpen() {
@@ -125,7 +125,7 @@
* @param src the bytes to write
* @return the number of bytes written, possibly zero
* @throws IOException in case of IO error
- * @since 1.0
+ * @since 19.0
*/
@Override
public int write(ByteBuffer src) throws IOException {
@@ -178,7 +178,7 @@
*
* @param embedded if {@code true} the builder creates an embedded {@link GraphOutput}
* @return this builder
- * @since 1.0
+ * @since 19.0
*/
public Builder<G, N, M> embedded(boolean embedded) {
this.embeddedGraphOutput = embedded;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
@@ -86,6 +87,13 @@
final int versionMinor;
private boolean printing;
+ /**
+ * See {@code org.graalvm.compiler.serviceprovider.BufferUtil}.
+ */
+ private static Buffer asBaseBuffer(Buffer obj) {
+ return obj;
+ }
+
GraphProtocol(WritableByteChannel channel, int major, int minor, boolean embedded) throws IOException {
if (major > MAJOR_VERSION || (major == MAJOR_VERSION && minor > MINOR_VERSION)) {
throw new IllegalArgumentException("Unrecognized version " + major + "." + minor);
@@ -328,7 +336,7 @@
}
private void flush() throws IOException {
- buffer.flip();
+ asBaseBuffer(buffer).flip();
/*
* Try not to let interrupted threads abort the write. There's still a race here but an
* interrupt that's been pending for a long time shouldn't stop this writing.
@@ -411,12 +419,12 @@
while (b.position() < limit) {
int toWrite = Math.min(limit - b.position(), buffer.capacity());
ensureAvailable(toWrite);
- b.limit(b.position() + toWrite);
+ asBaseBuffer(b).limit(b.position() + toWrite);
try {
buffer.put(b);
written += toWrite;
} finally {
- b.limit(limit);
+ asBaseBuffer(b).limit(limit);
}
}
return written;
@@ -430,7 +438,7 @@
int sizeInBytes = b.length * 4;
ensureAvailable(sizeInBytes);
buffer.asIntBuffer().put(b);
- buffer.position(buffer.position() + sizeInBytes);
+ asBaseBuffer(buffer).position(buffer.position() + sizeInBytes);
}
}
@@ -442,7 +450,7 @@
int sizeInBytes = b.length * 8;
ensureAvailable(sizeInBytes);
buffer.asDoubleBuffer().put(b);
- buffer.position(buffer.position() + sizeInBytes);
+ asBaseBuffer(buffer).position(buffer.position() + sizeInBytes);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java Fri Jun 28 14:36:42 2019 +0530
@@ -61,8 +61,8 @@
* <a href="doc-files/diamond.bgv">diamond.bgv</a> file generated from the above diamond structure
* graph.
* <p>
- * The primary <b>IGV</b> focus is on graphs used by Graal compiler. As such they aren't plain
- * graphs, but contain various compiler oriented attributes:
+ * The primary <b>IGV</b> focus is on graphs used by the compiler. As such they aren't plain graphs,
+ * but contain various compiler oriented attributes:
* <ul>
* <li>{@linkplain org.graalvm.graphio.GraphBlocks code blocks} information</li>
* <li>{@linkplain org.graalvm.graphio.GraphElements method and fields} information</li>
@@ -80,7 +80,7 @@
* <a href="http://wiki.apidesign.org/wiki/Singletonizer">singletonizer</a> API pattern again - e.g.
* no need to change your existing data structures, just implement the operations provided by the
* interfaces you pass into the builder. By combining these interfaces together you can get as rich,
- * colorful, source linked graphs as Graal compiler produces to describe its optimizations.
+ * colorful, source linked graphs as the compiler produces to describe its optimizations.
*/
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -28,7 +28,7 @@
import jdk.internal.vm.compiler.collections.EconomicMap;
import jdk.internal.vm.compiler.collections.Equivalence;
-import org.graalvm.compiler.test.GraalTest;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.util.ObjectSizeEstimate;
import org.junit.Assume;
import org.junit.Test;
@@ -40,7 +40,7 @@
*/
@Test
public void testSize() {
- Assume.assumeTrue("Not working in JDK9 due to module visibility.", GraalTest.Java8OrEarlier);
+ Assume.assumeTrue("Not working in JDK9 due to module visibility.", JavaVersionUtil.JAVA_SPEC <= 8);
EconomicMap<Object, Object> map = EconomicMap.create(Equivalence.IDENTITY);
assertEquals(49, ObjectSizeEstimate.forObject(map).getTotalBytes());
@@ -59,7 +59,7 @@
*/
@Test
public void testCompress() {
- Assume.assumeTrue("Not working in JDK9 due to module visibility.", GraalTest.Java8OrEarlier);
+ Assume.assumeTrue("Not working in JDK9 due to module visibility.", JavaVersionUtil.JAVA_SPEC <= 8);
EconomicMap<Object, Object> map = EconomicMap.create();
// Measuring size of map with one entry.
--- a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c Wed Jun 26 14:28:47 2019 +0530
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -873,7 +873,6 @@
"launch=<command line> run debugger on event none\n"
"onthrow=<exception name> debug on throw none\n"
"onuncaught=y|n debug on any uncaught? n\n"
- "onjcmd=y|n start debug via jcmd? n\n"
"timeout=<timeout value> for listen/attach in milliseconds n\n"
"mutf8=y|n output modified utf-8 n\n"
"quiet=y|n control over terminal messages n\n"));
--- a/test/hotspot/jtreg/TEST.groups Wed Jun 26 14:28:47 2019 +0530
+++ b/test/hotspot/jtreg/TEST.groups Fri Jun 28 14:36:42 2019 +0530
@@ -275,6 +275,7 @@
-runtime/ErrorHandling/ErrorHandler.java \
-runtime/ErrorHandling/TestHeapDumpOnOutOfMemoryError.java \
-runtime/ErrorHandling/TimeoutInErrorHandlingTest.java \
+ -runtime/InvocationTests \
-runtime/logging/MonitorMismatchTest.java \
-runtime/memory/ReserveMemory.java \
-runtime/memory/RunUnitTestsConcurrently.java \
@@ -384,6 +385,7 @@
serviceability/ \
-runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
-runtime/CompressedOops/UseCompressedOops.java \
+ -runtime/InvocationTests \
-runtime/Thread/TestThreadDumpMonitorContention.java \
-:tier1_runtime \
-:tier1_serviceability \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/arguments/TestMaxRAMFlags.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package gc.arguments;
+
+/*
+ * @test TestMaxRAMFlags
+ * @key gc
+ * @bug 8222252
+ * @summary Verify correct MaxHeapSize and UseCompressedOops when MaxRAM and MaxRAMPercentage
+ * are specified.
+ * @library /test/lib
+ * @library /
+ * @requires vm.bits == "64"
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main gc.arguments.TestMaxRAMFlags
+ * @author bob.vandette@oracle.com
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestMaxRAMFlags {
+
+ private static void checkMaxRAMSize(long maxram, int maxrampercent, boolean forcecoop, long expectheap, boolean expectcoop) throws Exception {
+
+ ArrayList<String> args = new ArrayList<String>();
+ args.add("-XX:MaxRAM=" + maxram);
+ args.add("-XX:MaxRAMPercentage=" + maxrampercent);
+ if (forcecoop) {
+ args.add("-XX:+UseCompressedOops");
+ }
+
+ args.add("-XX:+PrintFlagsFinal");
+ args.add("-version");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ String stdout = output.getStdout();
+
+ long actualheap = new Long(getFlagValue("MaxHeapSize", stdout)).longValue();
+ if (actualheap != expectheap) {
+ throw new RuntimeException("MaxHeapSize value set to " + actualheap +
+ ", expected " + expectheap + " when running with the following flags: " + Arrays.asList(args).toString());
+ }
+
+ boolean actualcoop = getFlagBoolValue("UseCompressedOops", stdout);
+ if (actualcoop != expectcoop) {
+ throw new RuntimeException("UseCompressedOops set to " + actualcoop +
+ ", expected " + expectcoop + " when running with the following flags: " + Arrays.asList(args).toString());
+ }
+ }
+
+ private static long getHeapBaseMinAddress() throws Exception {
+ ArrayList<String> args = new ArrayList<String>();
+ args.add("-XX:+PrintFlagsFinal");
+ args.add("-version");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ String stdout = output.getStdout();
+ return (new Long(getFlagValue("HeapBaseMinAddress", stdout)).longValue());
+ }
+
+ private static String getFlagValue(String flag, String where) {
+ Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
+ if (!m.find()) {
+ throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+ }
+ String match = m.group();
+ return match.substring(match.lastIndexOf(" ") + 1, match.length());
+ }
+
+ private static boolean getFlagBoolValue(String flag, String where) {
+ Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where);
+ if (!m.find()) {
+ throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+ }
+ return m.group(1).equals("true");
+ }
+
+ public static void main(String args[]) throws Exception {
+ // Tests
+ // 1. Verify that MaxRAMPercentage overrides UseCompressedOops Ergo
+ // 2. Verify that UseCompressedOops forces compressed oops limit even
+ // when other flags are specified.
+
+ long oneG = 1L * 1024L * 1024L * 1024L;
+
+ // Hotspot startup logic reduces MaxHeapForCompressedOops by HeapBaseMinAddress
+ // in order to get zero based compressed oops offsets.
+ long heapbaseminaddr = getHeapBaseMinAddress();
+ long maxcoopheap = TestUseCompressedOopsErgoTools.getMaxHeapForCompressedOops(new String [0]) - heapbaseminaddr;
+
+ // Args: MaxRAM , MaxRAMPercentage, forcecoop, expect heap, expect coop
+ checkMaxRAMSize(maxcoopheap - oneG, 100, false, maxcoopheap - oneG, true);
+ checkMaxRAMSize(maxcoopheap + oneG, 100, false, maxcoopheap + oneG, false);
+ checkMaxRAMSize(maxcoopheap + oneG, 100, true, maxcoopheap, true);
+ }
+}
--- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java Fri Jun 28 14:36:42 2019 +0530
@@ -95,21 +95,28 @@
new LogMessageWithLevel("Post Evacuate Collection Set", Level.INFO),
new LogMessageWithLevel("Other", Level.INFO),
- // Update RS
- new LogMessageWithLevel("Update RS", Level.DEBUG),
+ // Merge Heap Roots
+ new LogMessageWithLevel("Merge Heap Roots", Level.INFO),
+ new LogMessageWithLevel("Remembered Sets", Level.DEBUG),
+ new LogMessageWithLevel("Merged Sparse", Level.DEBUG),
+ new LogMessageWithLevel("Merged Fine", Level.DEBUG),
+ new LogMessageWithLevel("Merged Coarse", Level.DEBUG),
+ new LogMessageWithLevel("Hot Card Cache", Level.DEBUG),
+ new LogMessageWithLevel("Log Buffers", Level.DEBUG),
new LogMessageWithLevel("Processed Buffers", Level.DEBUG),
- new LogMessageWithLevel("Scanned Cards", Level.DEBUG),
+ new LogMessageWithLevel("Dirty Cards", Level.DEBUG),
new LogMessageWithLevel("Skipped Cards", Level.DEBUG),
- new LogMessageWithLevel("Scan HCC", Level.DEBUG),
- // Scan RS
- new LogMessageWithLevel("Scan RS", Level.DEBUG),
+ // Scan Heap Roots
+ new LogMessageWithLevel("Scan Heap Roots", Level.DEBUG),
new LogMessageWithLevel("Scanned Cards", Level.DEBUG),
- new LogMessageWithLevel("Claimed Cards", Level.DEBUG),
- new LogMessageWithLevel("Skipped Cards", Level.DEBUG),
+ new LogMessageWithLevel("Scanned Blocks", Level.DEBUG),
+ new LogMessageWithLevel("Claimed Chunks", Level.DEBUG),
+ // Code Roots Scan
+ new LogMessageWithLevel("Code Root Scan", Level.DEBUG),
// Object Copy
new LogMessageWithLevel("Object Copy", Level.DEBUG),
- new LogMessageWithLevel("Scanned Cards", Level.DEBUG),
- new LogMessageWithLevel("Claimed Cards", Level.DEBUG),
+ new LogMessageWithLevel("LAB Waste", Level.DEBUG),
+ new LogMessageWithLevel("LAB Undo Waste", Level.DEBUG),
// Ext Root Scan
new LogMessageWithLevel("Thread Roots", Level.TRACE),
new LogMessageWithLevel("Universe Roots", Level.TRACE),
@@ -133,6 +140,7 @@
new LogMessageWithLevel("Table Fixup", Level.DEBUG),
new LogMessageWithLevel("Expand Heap After Collection", Level.DEBUG),
new LogMessageWithLevel("Region Register", Level.DEBUG),
+ new LogMessageWithLevel("Prepare Heap Roots", Level.DEBUG),
// Free CSet
new LogMessageWithLevel("Free Collection Set", Level.DEBUG),
new LogMessageWithLevel("Free Collection Set Serial", Level.TRACE),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokeinterface/Checker.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package invokeinterface;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class Checker extends shared.Checker {
+ private Class interfaceClass;
+
+ public Checker(Class interfaceClass, Class dynamicTargetClass) {
+ super(interfaceClass, dynamicTargetClass);
+
+ if (staticTargetClass.isInterface()) {
+ this.interfaceClass = staticTargetClass;
+ } else {
+ throw new RuntimeException("Static target class should be an interface.");
+ }
+ }
+
+ public String check (Class callerClass) {
+ // Check access rights to interface for caller
+ if (!checkAccess(interfaceClass, callerClass)) {
+ return "java.lang.IllegalAccessError";
+ }
+
+ // NSME is thrown when interface doesn't declare the method
+ if (getDeclaredMethod(interfaceClass) == null) {
+ return "java.lang.NoSuchMethodError";
+ }
+
+ // 9.1.5 Access to Interface Member Names
+ // "All interface members are implicitly public. They are
+ // accessible outside the package where the interface is
+ // declared if the interface is also declared public or
+ // protected, in accordance with the rules of 6.6."
+
+ // Search for method declaration in the hierarchy
+ Class klass = dynamicTargetClass;
+
+ while (klass != Object.class) {
+ Method method = getDeclaredMethod(klass);
+
+ if (method != null) {
+ int modifiers = method.getModifiers();
+
+ // Check whether obtained method is public and isn't abstract
+ if ( Modifier.isPublic(modifiers))
+ {
+ if (Modifier.isAbstract(modifiers)) {
+ return "java.lang.AbstractMethodError";
+ } else {
+ return String.format("%s.%s"
+ , method.getDeclaringClass().getSimpleName()
+ , methodName
+ );
+ }
+ } else {
+ // IAE is thrown when located method isn't PUBLIC
+ // or private. Private methods are skipped when
+ // looking for an interface method.
+ if (!Modifier.isPrivate(modifiers)) {
+ return "java.lang.IllegalAccessError";
+ }
+ }
+ }
+
+ klass = klass.getSuperclass();
+ }
+
+ // No method declaration is found
+ return "java.lang.AbstractMethodError";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokeinterface/ClassGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package invokeinterface;
+
+import jdk.internal.org.objectweb.asm.Opcodes;
+import shared.GenericClassGenerator;
+
+/*******************************************************************/
+class ClassGenerator extends GenericClassGenerator<ClassGenerator> {
+ public ClassGenerator(String fullClassName) {
+ super(fullClassName);
+ }
+
+ public ClassGenerator(String fullClassName, String parentClassName) {
+ super(fullClassName, parentClassName);
+ }
+
+ public ClassGenerator(String fullClassName, String parentClassName, int flags) {
+ super(fullClassName, parentClassName, flags);
+ }
+
+ public ClassGenerator(String fullClassName, String parentClassName, int flags, String[] implementedInterfaces) {
+ super(fullClassName, parentClassName, flags, implementedInterfaces);
+ }
+
+ // Add target method call site into current class
+ public ClassGenerator addCaller(String targetClass) {
+ return super.addCaller(targetClass, Opcodes.INVOKEINTERFACE);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokeinterface/Generator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * INVOKE_INTERFACE EXPECTED RESULTS
+ *
+ * Let C be the class of objectref. The actual method to be invoked is selected
+ * by the following lookup procedure:
+ * - If C contains a declaration for an instance method with the same name
+ * and descriptor as the resolved method, then this is the method to be
+ * invoked, and the lookup procedure terminates.
+ *
+ * - Otherwise, if C has a superclass, this same lookup procedure is
+ * performed recursively using the direct superclass of C; the method to be
+ * invoked is the result of the recursive invocation of this lookup
+ * procedure.
+ *
+ * Otherwise, if the class of objectref does not implement the resolved
+ * interface, invokeinterface throws an IncompatibleClassChangeError?.
+ *
+ * Otherwise, if no method matching the resolved name and descriptor is
+ * selected, invokeinterface throws an AbstractMethodError?.
+ *
+ * Otherwise, if the selected method is not public, invokeinterface throws an
+ * IllegalAccessError. Note that it cannot be private because private methods
+ * are ignored when searching for an interface method.
+ *
+ * My translation:
+ * 1. Resolve compile-time class/method.
+ * 2. Look up runtime class C, if it contains a name/signature match,
+ * and it is not private, invoke it.
+ * 3. If it does not, recursively lookup direct superclass of C.
+ * 4. If selected method is not public, throw IllegalAccessError
+ *
+ * InvokeInterface Results:
+ * - A interface class, declares A.m
+ * - A compile-time resolved class
+ * - C runtime resolved class
+ * - InvokeInterface will ALWAYS invoke C.m if C.m exists and is not private,
+ * regardless of overriding or accessibility
+ * - InvokeInterface will invoke a non-private B.m if C.m does not exist,
+ * regardless of overriding or accessibility
+ *
+ * Note: assuming Interface is public
+ *
+ * TODO: member interfaces can be protected and private and have special hiding
+ * rules (JLS 8.5)
+ */
+
+package invokeinterface;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import shared.AbstractGenerator;
+import shared.AccessType;
+import shared.Utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Generator extends AbstractGenerator {
+ public Generator(String[] args) {
+ super(args);
+ }
+
+ protected Checker getChecker(Class paramClass, Class targetClass) {
+ return new Checker(paramClass, targetClass);
+ }
+
+ public static void main (String[] args) throws Exception {
+ new Generator(args).run();
+ }
+
+ private void run() throws Exception {
+ // Specify package names
+ String pkg1 = "a.";
+ String pkg2 = "b.";
+ String pkg3 = "c.";
+ String pkgIntf = "i.";
+ String[] packages = new String[] { "", pkg1, pkg2, pkg3, pkgIntf };
+
+ int testNum = 0;
+ boolean isPassed = true;
+
+ // Hierarchy
+ // The following triples will be used during further
+ // hierarchy construction and will specify packages for A, B and C
+ String[][] packageSets = new String[][] {
+ { "", "", "", ""}
+ , { "", "", "", pkgIntf }
+
+ , { "", pkg1, pkg1, "" }
+ , { "", pkg1, pkg1, pkg1 }
+ , { "", pkg1, pkg1, pkgIntf }
+
+ , { "", pkg1, pkg2, "" }
+ , { "", pkg1, pkg2, pkg1}
+ , { "", pkg1, pkg2, pkg2}
+ , { "", pkg1, pkg2, pkgIntf}
+
+ , { pkg1, pkg1, pkg1, pkg1 }
+ , { pkg1, pkg1, pkg1, pkgIntf }
+
+ , { pkg1, pkg1, pkg2, pkg1 }
+ , { pkg1, pkg1, pkg2, pkg2 }
+ , { pkg1, pkg1, pkg2, pkgIntf }
+
+ , { pkg1, pkg2, pkg1, pkg1 }
+ , { pkg1, pkg2, pkg1, pkg2 }
+ , { pkg1, pkg2, pkg1, pkgIntf }
+
+ , { pkg1, pkg2, pkg2, pkg1 }
+ , { pkg1, pkg2, pkg2, pkg2 }
+ , { pkg1, pkg2, pkg2, pkgIntf }
+ };
+
+ String [] header = new String[] {
+ String.format("%30s %68s %25s", "Method access modifiers", "Call site location", "Status")
+ , String.format("%5s %-12s %-12s %-12s %-12s %7s %7s %7s %7s %7s %7s %7s"
+ , " # "
+ , "A.m()"
+ , "B.m()"
+ , "C.m()"
+ , "I.m()"
+ , " C "
+ , "pkgC "
+ , " B "
+ , " pkgB"
+ , " A "
+ , "pkgA"
+ , "Intf"
+ )
+ , "--------------------------------------------------------------------------------------------------------------------"
+ };
+
+ for (String aHeader : header) {
+ System.out.println(aHeader);
+ }
+
+ for (String[] pkgSet : packageSets) {
+ String packageA = pkgSet[0];
+ String packageB = pkgSet[1];
+ String packageC = pkgSet[2];
+
+ String packageIntf = pkgSet[3];
+
+ String classNameA = packageA + "A";
+ String classNameB = packageB + "B";
+ String classNameC = packageC + "C";
+ String classNameIntf = packageIntf + "I";
+
+ // For all possible access modifier combinations
+ for (AccessType accessA : AccessType.values()) {
+ for (AccessType accessB : AccessType.values()) {
+ for (AccessType accessC : AccessType.values()) {
+ for (AccessType accessIntf : AccessType.values()) {
+
+ if (accessIntf == AccessType.UNDEF) {
+ continue;
+ }
+
+ for (int I = 0; I < 4; I++) {
+ boolean isAbstractA = ((I & 1) != 0);
+ boolean isAbstractB = ((I & 2) != 0);
+
+ testNum++;
+
+ Map<String, byte[]> classes = new HashMap<String, byte[]>();
+
+ // TODO: add non-PUBLIC interfaces, then particular call sites will affect the results
+
+ // Generate interface Intf
+ classes.put(
+ classNameIntf
+ , new ClassGenerator( classNameIntf
+ , "java.lang.Object"
+ , ACC_ABSTRACT | ACC_INTERFACE | accessIntf.value())
+ .addTargetMethod(AccessType.PUBLIC)
+ .getClassFile()
+ );
+
+ // Generate class A
+ classes.put(
+ classNameA
+ , new ClassGenerator( classNameA
+ , "java.lang.Object"
+ , ACC_PUBLIC | ( isAbstractA ? ACC_ABSTRACT : 0))
+ .addTargetMethod(accessA)
+ .addCaller(classNameIntf)
+ .getClassFile()
+ );
+
+ // Generate class B
+ classes.put(
+ classNameB
+ , new ClassGenerator( classNameB
+ , classNameA
+ , ACC_PUBLIC | ( isAbstractB ? ACC_ABSTRACT : 0)
+ , new String[] { Utils.getInternalName(classNameIntf) })
+ .addTargetMethod(accessB)
+ .addCaller(classNameIntf)
+ .getClassFile()
+ );
+
+ // Generate class C
+ classes.put( classNameC
+ , new ClassGenerator( classNameC, classNameB )
+ .addTargetMethod(accessC)
+ .addCaller(classNameIntf)
+ .getClassFile()
+ );
+
+ // Generate package callers
+ for (String pkg : packages) {
+ classes.put( pkg+"Caller"
+ , new ClassGenerator(pkg+"Caller")
+ .addCaller(classNameIntf)
+ .getClassFile()
+ );
+ }
+
+ String caseDescription =
+ String.format("%-12s %-12s %-12s %-12s| "
+ , (isAbstractA ? "! " : " ") + classNameA + " " + accessA
+ , (isAbstractB ? "! " : " ") + classNameB + " " + accessB
+ , classNameC + " " + accessC
+ , accessIntf + " " + classNameIntf
+ );
+
+ String[] callSites = new String[] {
+ classNameC
+ , packageC+"Caller"
+ , classNameB
+ , packageB+"Caller"
+ , classNameA
+ , packageA+"Caller"
+ , packageIntf+"Caller"
+ };
+
+ boolean result = exec(classes, caseDescription, classNameIntf, classNameC, callSites);
+ isPassed = isPassed && result;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Print footer
+
+ for (int i = header.length-1; i >= 0; i--) {
+ System.out.println(header[i]);
+ }
+
+ if (executeTests) {
+ System.out.printf("\nEXECUTION STATUS: %s\n", (isPassed? "PASSED" : "FAILED"));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokeinterfaceTests.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8224137
+ * @summary Run invokeinterface invocation tests
+ * @library /test/lib
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.misc
+ * @compile shared/AbstractGenerator.java shared/AccessCheck.java shared/AccessType.java
+ * shared/Caller.java shared/ExecutorGenerator.java shared/Utils.java
+ * shared/ByteArrayClassLoader.java shared/Checker.java shared/GenericClassGenerator.java
+ * @compile invokeinterface/Checker.java invokeinterface/ClassGenerator.java
+ * invokeinterface/Generator.java
+ *
+ * @run main/othervm/timeout=1800 invokeinterfaceTests
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class invokeinterfaceTests {
+
+ public static void runTest(String classFileVersion, String option) throws Exception {
+ System.out.println("\ninvokeinterface invocation tests, option: " + option +
+ ", class file version: " + classFileVersion);
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false, "-Xmx128M", option,
+ "invokeinterface.Generator", "--classfile_version=" + classFileVersion);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ try {
+ output.shouldContain("EXECUTION STATUS: PASSED");
+ output.shouldHaveExitValue(0);
+ } catch (Throwable e) {
+ System.out.println(
+ "\nNote that an entry such as 'B.m/C.m' in the failure chart means that" +
+ " the test case failed because method B.m was invoked but the test " +
+ "expected method C.m to be invoked. Similarly, a result such as 'AME/C.m'" +
+ " means that an AbstractMethodError exception was thrown but the test" +
+ " case expected method C.m to be invoked.");
+ System.out.println(
+ "\nAlso note that passing --dump to invokeinterface.Generator will" +
+ " dump the generated classes (for debugging purposes).\n");
+
+ System.exit(1);
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ // Get current major class file version and test with it.
+ byte klassbuf[] = InMemoryJavaCompiler.compile("blah", "public class blah { }");
+ int major_version = klassbuf[6] << 8 | klassbuf[7];
+ runTest(String.valueOf(major_version), "-Xint");
+ runTest(String.valueOf(major_version), "-Xcomp");
+
+ // Test old class file version.
+ runTest("51", "-Xint"); // JDK-7
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokespecial/Checker.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package invokespecial;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class Checker extends shared.Checker {
+
+ public Checker(Class staticTargetClass, Class dynamicTargetClass) {
+ super(staticTargetClass, dynamicTargetClass);
+ }
+
+ public String check (Class callerClass) {
+ /*
+ * If objectref is null, the invokespecial instruction throws a NullPointerException.
+ */
+ if (dynamicTargetClass == null) {
+ return "java.lang.NullPointerException";
+ }
+
+ /*
+ * TODO: find a citiation from spec for this case
+ */
+ Method resolvedMethod;
+ try {
+ // May throw VerifyError
+ resolvedMethod = getMethodInHierarchy(staticTargetClass);
+ } catch (Throwable e) {
+ return e.getClass().getName();
+ }
+
+ if (resolvedMethod == null) {
+ return "java.lang.NoSuchMethodError";
+ }
+
+ /*
+ * If:
+ * - the resolved method is protected (4.7)
+ * - it is a member of a superclass of the current class
+ * - the method is not declared in the same run-time package (5.3) as the current class
+ * then:
+ * the class of objectref must be either the current class or a subclass of the
+ * current class.
+ */
+
+ if (Modifier.isProtected(resolvedMethod.getModifiers())) {
+ Method methodInSuperclass = getMethodInHierarchy(resolvedMethod.getDeclaringClass().getSuperclass());
+
+ if (methodInSuperclass != null) {
+ String resolvedMethodPkg = getClassPackageName(resolvedMethod.getDeclaringClass());
+ String methodInSuperclassPkg = getClassPackageName(methodInSuperclass.getDeclaringClass());
+
+ if (!resolvedMethodPkg.equals(methodInSuperclassPkg)) {
+ //TODO: clarify this
+// if (callerClass == methodInSuperclass.getDeclaringClass()) {
+// return "java.lang.IllegalAccessError";
+// }
+ }
+ }
+ }
+
+ /*
+ * The resolved method is selected for invocation unless all of
+ * the following conditions are true:
+ * * TODO: The ACC_SUPER flag (see Table 4.1, "Class access and property
+ * modifiers") is set for the current class.
+ * * The class of the resolved method is a superclass of the
+ * current class - assumed by construction procedure
+ *
+ * * The resolved method is not an instance initialization method (3.9).
+ */
+ if (!"<init>".equals(methodName)) {
+ /*
+ * Let C be the direct superclass of the current class:
+ * * If C contains a declaration for an instance method with the same
+ * name and descriptor as the resolved method, then this method will be
+ * invoked. The lookup procedure terminates.
+ * * Otherwise, if C has a superclass, this same lookup procedure is
+ * performed recursively using the direct superclass of C. The method to
+ * be invoked is the result of the recursive invocation of this lookup
+ * procedure.
+ * * Otherwise, an AbstractMethodError is raised.
+ * TODO: so far, sometimes NSME is thrown
+ */
+ Class klass = dynamicTargetClass.getSuperclass();
+
+ while (klass != Object.class) {
+ Method method = getDeclaredMethod(klass);
+
+ if (method != null) {
+ /*
+ * If the resolved method is a class (static) method, the
+ * invokespecial instruction throws an IncompatibleClassChangeError.
+ */
+ if (Modifier.isStatic(method.getModifiers())) {
+ return "java.lang.IncompatibleClassChangeError";
+ }
+
+ // Check access rights
+ if ( checkAccess(method, callerClass)
+// && !(
+// Modifier.isProtected(method.getModifiers())
+// && (
+// staticTargetClass.isAssignableFrom(callerClass)
+// || getClassPackageName(staticTargetClass).equals(getClassPackageName(callerClass))
+// )
+//
+// )
+ )
+ {
+ return String.format("%s.%s"
+ , method.getDeclaringClass().getSimpleName()
+ , methodName
+ );
+ } else {
+ // IAE is thrown when located method can't be accessed from the call site
+ return "java.lang.IllegalAccessError";
+ }
+ }
+
+ klass = klass.getSuperclass();
+ }
+
+ return "java.lang.AbstractMethodError";
+ } else {
+ // The resolved method is an instance initialization method (3.9).
+ }
+
+ // TODO: change
+ return "---";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokespecial/ClassGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package invokespecial;
+
+import jdk.internal.org.objectweb.asm.Opcodes;
+import shared.GenericClassGenerator;
+
+/*******************************************************************/
+class ClassGenerator extends GenericClassGenerator<ClassGenerator> {
+ public ClassGenerator(String fullClassName, String parentClassName, int flags) {
+ super(fullClassName, parentClassName, flags);
+ }
+
+ // Add target method call site into current class
+ public ClassGenerator addCaller(String targetClass) {
+ return super.addCaller(targetClass, Opcodes.INVOKESPECIAL);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokespecial/Generator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * INVOKESPECIAL EXPECTED RESULTS
+ *
+ * From JVMS 3rd edition: invokespecial instruction:
+ *
+ * Invoke instance method; special handling for superclass, private, and instance
+ * initialization method invocations
+ *
+ * The named method is resolved (5.4.3.3). Finally, if the resolved method is
+ * protected (4.7), and it is a member of a superclass of the current class, and
+ * the method is not declared in the same run-time package (5.3) as the current
+ * class, then the class of objectref must be either the current class or a
+ * subclass of the current class.
+ *
+ * Next, the resolved method is selected for invocation unless all of the
+ * following conditions are true:
+ * * The ACC_SUPER flag (see Table 4.1, "Class access and property modifiers") is set for the current class.
+ * * The class of the resolved method is a superclass of the current class.
+ * * The resolved method is not an instance initialization method (3.9).
+ *
+ * If the above conditions are true, the actual method to be invoked is selected
+ * by the following lookup procedure. Let C be the direct superclass of the
+ * current class:
+ * * If C contains a declaration for an instance method with the same name and
+ * descriptor as the resolved method, then this method will be invoked.
+ * The lookup procedure terminates.
+ *
+ * * Otherwise, if C has a superclass, this same lookup procedure is performed
+ * recursively using the direct superclass of C. The method to be invoked is
+ * the result of the recursive invocation of this lookup procedure.
+ *
+ * * Otherwise, an AbstractMethodError? is raised.
+ *
+ * During resolution of the symbolic reference to the method, any of the
+ * exceptions pertaining to method resolution documented in Section 5.4.3.3 can be
+ * thrown.
+ *
+ * Otherwise, if the resolved method is an instance initialization method, and the
+ * class in which it is declared is not the class symbolically referenced by the
+ * instruction, a NoSuchMethodError? is thrown.
+ *
+ * Otherwise, if the resolved method is a class (static) method, the invokespecial
+ * instruction throws an IncompatibleClassChangeError?.
+ *
+ * Otherwise, if no method matching the resolved name and descriptor is selected,
+ * invokespecial throws an AbstractMethodError?.
+ *
+ * Otherwise, if the selected method is abstract, invokespecial throws an
+ * AbstractMethodError?.
+ *
+ * RUNTIME EXCEPTIONS
+ *
+ * Otherwise, if objectref is null, the invokespecial instruction throws a NullPointerException?.
+ *
+ * Otherwise, if the selected method is native and the code that implements the
+ * method cannot be bound, invokespecial throws an UnsatisfiedLinkError?.
+ *
+ * NOTES
+ *
+ * The difference between the invokespecial and the invokevirtual instructions is
+ * that invokevirtual invokes a method based on the class of the object. The
+ * invokespecial instruction is used to invoke instance initialization methods
+ * (3.9) as well as private methods and methods of a superclass of the current
+ * class.
+ *
+ * ACC_SUPER:
+ *
+ * The setting of the ACC_SUPER flag indicates which of two alternative semantics
+ * for its invokespecial instruction the Java virtual machine is to express; the
+ * ACC_SUPER flag exists for backward compatibility for code compiled by Sun's
+ * older compilers for the Java programming language. All new implementations of
+ * the Java virtual machine should implement the semantics for invokespecial
+ * documented in this specification. All new compilers to the instruction set of
+ * the Java virtual machine should set the ACC_SUPER flag. Sun's older compilers
+ * generated ClassFile? flags with ACC_SUPER unset. Sun's older Java virtual
+ * machine implementations ignore the flag if it is set.
+ *
+ * ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the
+ * invokespecial instruction.
+ *
+ * My Translation:
+ * 1. compile-time resolved class B
+ * 2. A,B,C direct superclass relationships
+ * 3. If B.m is protected
+ * - if the caller is in B
+ * then runtime resolved class must be in B or C
+ * - if the caller is in C
+ * then runtime resolved class must be in C
+ * TODO: otherwise what is thrown? <noWikiWord>AbstractMethodError?
+ * 4. If B.m is an instance initialization method,
+ * invoke B.m
+ * 5. If backward compatible caller does not set ACC_SUPER,
+ * invoke B.m
+ * 6. If B is not a superclass of the caller, e.g. A is caller, or unrelated X
+ * is the caller, invoke B.m
+ * 7. Otherwise:
+ * If superclass of caller contains name/sig match, use it
+ * Else, recursively through that superclass
+ * 8. If none found, throw AbstractMethodError
+ *
+ * Note: there is NO mention of overriding or accessibility in determining
+ * resolved method, except for if the compile-time type is protected.
+ *
+ * Case 1: B.m is protected
+ * Caller in A: if runtime resolved class in A.m, AbstractMethodError
+ * Caller in B: if runtime resolved class in A.m, AbstractMethodError
+ * Case 2: B.m is an instance initialization method
+ * Always invoke B.m
+ * Case 3: older javac, caller does not set ACC_SUPER
+ * Always invoke B.m
+ * Case 4: A or X (not in hierarchy) calls invokespecial on B.m, invoke B.m
+ * Case 5: Caller in B:
+ * if A.m exists, call it, else <noWikiWord>AbstractMethodError
+ * Caller in C:
+ * if B.m exists, call it
+ * if B.m does not exist, and A.m exists, call it
+ */
+
+// TODO: classes without ACC_SUPER attribute
+// TODO: B.m is an instance initialization method
+
+/*
+ * invokespecial <method-spec>
+ *
+ * invokespecial is used in certain special cases to invoke a method
+ * Specifically, invokespecial is used to invoke:
+ * - the instance initialization method, <init>
+ * - a private method of this
+ * - a method in a superclass of this
+ *
+ * The main use of invokespecial is to invoke an object's instance
+ * initialization method, <init>, during the construction phase for a new object.
+ * For example, when you write in Java:
+ *
+ * new StringBuffer()
+ *
+ * code like the following is generated:
+ * new java/lang/StringBuffer ; create a new StringBuffer
+ * dup ; make an extra reference to the new instance
+ * ; now call an instance initialization method
+ * invokespecial java/lang/StringBuffer/<init>()V
+ * ; stack now contains an initialized StringBuffer.
+ *
+ * invokespecial is also used by the Java language by the 'super' keyword to
+ * access a superclass's version of a method. For example, in the class:
+ *
+ * class Example {
+ * // override equals
+ * public boolean equals(Object x) {
+ * // call Object's version of equals
+ * return super.equals(x);
+ * }
+ * }
+ *
+ * the 'super.equals(x)' expression is compiled to:
+ *
+ * aload_0 ; push 'this' onto the stack
+ * aload_1 ; push the first argument (i.e. x) onto the stack
+ * ; now invoke Object's equals() method.
+ * invokespecial java/lang/Object/equals(Ljava/lang/Object;)Z
+ *
+ * Finally, invokespecial is used to invoke a private method. Remember that
+ * private methods are only visible to other methods belonging the same class as
+ * the private method.
+ *
+ * Before performing the method invocation, the class and the method identified
+ * by <method-spec> are resolved. See Chapter 9 for a description of how methods
+ * are resolved.
+ *
+ * invokespecial first looks at the descriptor given in <method-spec>, and
+ * determines how many argument words the method takes (this may be zero). It
+ * pops these arguments off the operand stack. Next it pops objectref (a
+ * reference to an object) off the operand stack. objectref must be an instance
+ * of the class named in <method-spec>, or one of its subclasses. The interpreter
+ * searches the list of methods defined by the class named in <method-spec>,
+ * looking for a method called methodname whose descriptor is descriptor. This
+ * search is not based on the runtime type of objectref, but on the compile time
+ * type given in <method-spec>.
+ *
+ * Once a method has been located, invokespecial calls the method. First, if
+ * the method is marked as synchronized, the monitor associated with objectref is
+ * entered. Next, a new stack frame structure is established on the call stack.
+ * Then the arguments for the method (which were popped off the current method's
+ * operand stack) are placed in local variables of the new stack frame structure.
+ * arg1 is stored in local variable 1, arg2 is stored in local variable 2 and so
+ * on. objectref is stored in local variable 0 (the local variable used for the
+ * special Java variable this). Finally, execution continues at the first
+ *instruction in the bytecode of the new method.
+ *
+ * Methods marked as native are handled slightly differently. For native
+ * methods, the runtime system locates the platform-specific code for the method,
+ * loading it and linking it into the JVM if necessary. Then the native method
+ * code is executed with the arguments popped from the operand stack. The exact
+ * mechanism used to invoke native methods is implementation-specific.
+ *
+ * When the method called by invokespecial returns, any single (or double) word
+ * return result is placed on the operand stack of the current method. If the
+ * invoked method was marked as synchronized, the monitor associated with
+ * objectref is exited. Execution continues at the instruction that follows
+ * invokespecial in the bytecode.
+ *
+ * Notes
+ *
+ * 1. In Java Virtual Machine implementations prior to version JDK 1.02, this
+ * instruction was called invokenonvirtual, and was less restrictive than
+ * invokespecial - it wasn't limited to invoking only superclass, private or
+ * <init> methods. The class access flag ACC_SUPER (see Chapter 4) is used to
+ * indicate which semantics are used by a class. In older class files, the
+ * ACC_SUPER flag is unset. In all new classes, the ACC_SUPER flag should be set,
+ * indicating that the restrictions enforced by invokespecial are obeyed. (In
+ * practice, all the common uses of invokenonvirtual continue to be supported
+ * by invokespecial, so this change should have little impact on JVM users).
+ *
+ */
+
+package invokespecial;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import shared.AbstractGenerator;
+import shared.AccessType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Generator extends AbstractGenerator {
+ public static void main (String[] args) throws Exception {
+ new Generator(args).run();
+ }
+ public Generator(String[] args) {
+ super(args);
+ }
+
+ protected Checker getChecker(Class paramClass, Class targetClass) {
+ return new Checker(paramClass, targetClass);
+ }
+
+ public void run() throws Exception {
+ // Specify package names
+ String pkg1 = "a.";
+ String pkg2 = "b.";
+ String[] packages = new String[] { "", pkg1, pkg2 };
+
+ boolean isPassed = true;
+
+ // HIERARCHIES
+ // The following triples will be used during further
+ // hierarchy construction and will specify packages for A, B and C
+ String[][] packageSets = new String[][] {
+ { "", "", "" }
+ , { "", pkg1, pkg1 }
+ , { "", pkg1, pkg2 }
+ , { pkg1, "", pkg1 }
+ , { pkg1, "", pkg2 }
+ , { pkg1, pkg1, "" }
+ , { pkg1, pkg2, "" }
+ , { pkg1, pkg1, pkg1 }
+ , { pkg1, pkg1, pkg2 }
+ , { pkg1, pkg2, pkg1 }
+ , { pkg1, pkg2, pkg2 }
+ };
+
+ String [] header = new String[] {
+ String.format("%30s %35s", "Method access modifiers", "Call site location")
+ , String.format("%4s %-10s %-10s %-10s %7s %7s %7s %7s %7s %7s %7s"
+ , " # "
+ , "A.m()"
+ , "B.m()"
+ , "C.m()"
+ , " A "
+ , "pkgA"
+ , " B "
+ , " pkgB"
+ , " C "
+ , "pkgC "
+ , " X "
+ )
+ , "-----------------------------------------------------------------------------------------------------------"
+ };
+
+ // Print header
+ for (String str : header) {
+ System.out.println(str);
+ }
+
+ // Iterate over all interesting package combinations
+ for (String[] pkgSet : packageSets) {
+ String packageA = pkgSet[0];
+ String packageB = pkgSet[1];
+ String packageC = pkgSet[2];
+
+ String classNameA = packageA + "A";
+ String classNameB = packageB + "B";
+ String classNameC = packageC + "C";
+
+ // For all possible access modifier combinations
+ for (AccessType accessFlagA : AccessType.values()) {
+ for (AccessType accessFlagB : AccessType.values()) {
+ for (AccessType accessFlagC : AccessType.values()) {
+ Map<String, byte[]> classes = new HashMap<String, byte[]>();
+
+ String calleeClassName = classNameB;
+ int classFlags = ACC_PUBLIC;
+
+ // The following hierarhcy is created:
+ // c.C extends b.B extends a.A extends Object - base hierarchy
+ // X extends Object - external caller
+ // c.Caller, b.Caller, a.Caller extends Object - package callers
+
+ // Generate result storage
+ classes.put(
+ "Result"
+ , new ClassGenerator(
+ "Result"
+ , "java.lang.Object"
+ , ACC_PUBLIC
+ )
+ .addField(
+ ACC_PUBLIC | ACC_STATIC
+ , "value"
+ , "java.lang.String"
+ )
+ .getClassFile()
+ );
+
+ // Generate class A
+ classes.put(
+ classNameA
+ , new ClassGenerator(
+ classNameA
+ , "java.lang.Object"
+ , classFlags
+ )
+ .addTargetConstructor(accessFlagA)
+ .addTargetMethod(accessFlagA)
+ .addCaller(calleeClassName)
+ .getClassFile()
+ );
+
+ // Generate class B
+ classes.put(
+ classNameB
+ , new ClassGenerator(
+ classNameB
+ , classNameA
+ , classFlags
+ )
+ .addTargetConstructor(accessFlagB)
+ .addTargetMethod(accessFlagB)
+ .addCaller(calleeClassName)
+ .getClassFile()
+ );
+
+ // Generate class C
+ classes.put(
+ classNameC
+ , new ClassGenerator(
+ classNameC
+ , classNameB
+ , classFlags
+ )
+ .addTargetConstructor(accessFlagC)
+ .addTargetMethod(accessFlagC)
+ .addCaller(calleeClassName)
+ .getClassFile()
+ );
+
+ // Generate class X
+ String classNameX = "x.X";
+ classes.put(
+ classNameX
+ , new ClassGenerator(
+ classNameX
+ , "java.lang.Object"
+ , classFlags
+ )
+ .addTargetMethod(accessFlagC)
+ .addCaller(calleeClassName)
+ .getClassFile()
+ );
+
+ // Generate package callers
+ for (String pkg : packages) {
+ classes.put(
+ pkg+"Caller"
+ , new ClassGenerator(
+ pkg+"Caller"
+ , "java.lang.Object"
+ , classFlags
+ )
+ .addCaller(calleeClassName)
+ .getClassFile()
+ );
+ }
+
+ String[] callSites = new String[] {
+ classNameA
+ , packageA+"Caller"
+ , classNameB
+ , packageB+"Caller"
+ , classNameC
+ , packageC+"Caller"
+ , classNameX
+ };
+
+ String caseDescription = String.format(
+ "%-10s %-10s %-10s| "
+ , classNameA + " " + accessFlagA
+ , classNameB + " " + accessFlagB
+ , classNameC + " " + accessFlagC
+ );
+
+ boolean result = exec(classes, caseDescription, calleeClassName, classNameC, callSites);
+ isPassed = isPassed && result;
+ }
+ }
+ }
+ }
+
+ // Print footer
+ for (int i = header.length-1; i >= 0; i--) {
+ System.out.println(header[i]);
+ }
+
+ if (executeTests) {
+ System.out.printf("\nEXECUTION STATUS: %s\n", (isPassed? "PASSED" : "FAILED"));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokespecialTests.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8224137
+ * @summary Run invokespecial invocation tests
+ * @library /test/lib
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.misc
+ * @compile shared/AbstractGenerator.java shared/AccessCheck.java shared/AccessType.java
+ * shared/Caller.java shared/ExecutorGenerator.java shared/Utils.java
+ * shared/ByteArrayClassLoader.java shared/Checker.java shared/GenericClassGenerator.java
+ * @compile invokespecial/Checker.java invokespecial/ClassGenerator.java invokespecial/Generator.java
+ *
+ * @run main/othervm/timeout=1800 invokespecialTests
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class invokespecialTests {
+
+ public static void runTest(String classFileVersion, String option) throws Exception {
+ System.out.println("\ninvokespecial invocation tests, option: " + option +
+ ", class file version: " + classFileVersion);
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false, "-Xmx128M", option,
+ "invokespecial.Generator", "--classfile_version=" + classFileVersion);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ try {
+ output.shouldContain("EXECUTION STATUS: PASSED");
+ output.shouldHaveExitValue(0);
+ } catch (Throwable e) {
+ System.out.println(
+ "\nNote that an entry such as 'B.m/C.m' in the failure chart means that" +
+ " the test case failed because method B.m was invoked but the test " +
+ "expected method C.m to be invoked. Similarly, a result such as 'AME/C.m'" +
+ " means that an AbstractMethodError exception was thrown but the test" +
+ " case expected method C.m to be invoked.");
+ System.out.println(
+ "\nAlso note that passing --dump to invokespecial.Generator will" +
+ " dump the generated classes (for debugging purposes).\n");
+ System.exit(1);
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ // Get current major class file version and test with it.
+ byte klassbuf[] = InMemoryJavaCompiler.compile("blah", "public class blah { }");
+ int major_version = klassbuf[6] << 8 | klassbuf[7];
+ runTest(String.valueOf(major_version), "-Xint");
+ runTest(String.valueOf(major_version), "-Xcomp");
+
+ // Test old class file version.
+ runTest("51", "-Xint"); // JDK-7
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokevirtual/Checker.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package invokevirtual;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+
+public class Checker extends shared.Checker {
+ public Checker(Class staticTargetClass, Class dynamicTargetClass) {
+ super(staticTargetClass, dynamicTargetClass);
+ }
+
+ public String check (Class callerClass) {
+ Method m;
+ try {
+ // May cause java.lang.VerifyError
+ m = getOverriddenMethod();
+ } catch (Throwable e) {
+ return e.getClass().getName();
+ }
+
+ // Check method accessibility (it's a static property, according to JLS #6.6: Access Control)
+ if (m != null) {
+ Method staticTargetMethod = getDeclaredMethod(staticTargetClass);
+
+ if (checkAccess(staticTargetMethod, callerClass)) {
+ // Can't invoke abstract method
+ if ( Modifier.isAbstract(m.getModifiers())) {
+ return "java.lang.AbstractMethodError";
+ }
+
+ return String.format("%s.%s"
+ , m.getDeclaringClass().getSimpleName()
+ , methodName
+ );
+ } else {
+ // if method isn't accessible, IllegalAccessError is thrown
+ return "java.lang.IllegalAccessError";
+ }
+ } else {
+ // if method == null, NoSuchMethodError is thrown
+ return "java.lang.NoSuchMethodError";
+ }
+ }
+
+ public Method getOverriddenMethod() {
+ return getOverriddenMethod(staticTargetClass, dynamicTargetClass);
+ }
+
+ public Method getOverriddenMethod(Class staticTarget, Class dynamicTarget) {
+ // Assertion #1. C is a subclass of A
+ if (!staticTarget.isAssignableFrom(dynamicTarget)) {
+ return null;
+ }
+
+ Method staticTargetMethod = getDeclaredMethod(staticTarget);
+ Method dynamicTargetMethod = getDeclaredMethod(dynamicTarget);
+
+ if (staticTarget.equals(dynamicTarget)) {
+ return staticTargetMethod;
+ }
+
+ // TODO: ? need to find out the right behavior
+ if (staticTargetMethod == null) {
+ return null;
+ }
+
+ // Dynamic target doesn't have desired method, so check it's superclass
+ if (dynamicTargetMethod == null) {
+ return getOverriddenMethod(staticTarget, dynamicTarget.getSuperclass());
+ } else {
+ // Private method can't override anything
+ if (Modifier.isPrivate(dynamicTargetMethod.getModifiers())) {
+ return getOverriddenMethod(staticTarget, dynamicTarget.getSuperclass());
+ }
+ }
+
+ // TODO: abstract methods
+
+ //Assertion #3.a: A.m2 is PUB || PROT || (PP && PKG(A) == PKG(C))
+ int staticTargetModifiers = staticTargetMethod.getModifiers();
+ {
+ boolean isPublic = Modifier.isPublic(staticTargetModifiers);
+ boolean isProtected = Modifier.isProtected(staticTargetModifiers);
+ boolean isPrivate = Modifier.isPrivate(staticTargetModifiers) ;
+ String staticTargetPkg = getClassPackageName(staticTarget);
+ String dynamicTargetPkg = getClassPackageName(dynamicTarget);
+
+ if ( isPublic || isProtected
+ || ( !isPublic && !isProtected && !isPrivate
+ && staticTargetPkg.equals(dynamicTargetPkg)
+ ))
+ {
+ return dynamicTargetMethod;
+ }
+ }
+ // OR
+ //Assertion #3.b: exists m3: C.m1 != B.m3, A.m2 != B.m3, B.m3 overrides A.m2, C.m1 overrides B.m3
+ Class ancestor = dynamicTarget.getSuperclass();
+ while (ancestor != staticTarget) {
+ Method OverriddenM2 = getOverriddenMethod(staticTarget, ancestor);
+ Method m3 = getDeclaredMethod(ancestor);
+ Method m1 = getOverriddenMethod(ancestor, dynamicTarget);
+
+ if (m1 != null && m3 != null) {
+ if (m1.equals(dynamicTargetMethod) && m3.equals(OverriddenM2)) {
+ return dynamicTargetMethod;
+ }
+ } else {
+ if (m1 == null && dynamicTargetMethod == null
+ && m3 == null && OverriddenM2 == null)
+ {
+ return null;
+ }
+ }
+
+ ancestor = ancestor.getSuperclass();
+ }
+
+ return getOverriddenMethod(staticTarget, dynamicTarget.getSuperclass());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokevirtual/ClassGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package invokevirtual;
+
+import jdk.internal.org.objectweb.asm.Opcodes;
+import shared.GenericClassGenerator;
+
+/*******************************************************************/
+class ClassGenerator extends GenericClassGenerator<ClassGenerator> {
+ public ClassGenerator(String fullClassName) {
+ super(fullClassName);
+ }
+
+ public ClassGenerator(String fullClassName, String parentClassName) {
+ super(fullClassName, parentClassName);
+ }
+
+ public ClassGenerator(String fullClassName, String parentClassName, int flags) {
+ super(fullClassName, parentClassName, flags);
+ }
+
+ // Add target method call site into current class
+ public ClassGenerator addCaller(String targetClass) {
+ return super.addCaller(targetClass, Opcodes.INVOKEVIRTUAL);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokevirtual/Generator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package invokevirtual;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_ABSTRACT;
+import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import shared.AbstractGenerator;
+import shared.AccessType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Generator extends AbstractGenerator {
+ public Generator(String[] args) {
+ super(args);
+ }
+
+ public static void main (String[] args) throws Exception {
+ new Generator(args).run();
+ }
+
+ protected Checker getChecker(Class paramClass, Class targetClass) {
+ return new Checker(paramClass, targetClass);
+ }
+
+ private void run() throws Exception {
+ // Specify package names
+ String pkg1 = "a.";
+ String pkg2 = "b.";
+ String pkg3 = "c.";
+ String[] packages = new String[] { "", pkg1, pkg2, pkg3 };
+
+ boolean isPassed = true;
+
+ // Hierarchy
+ // The following triples will be used during further
+ // hierarchy construction and will specify packages for A, B and C
+ String[][] packageSets = new String[][] {
+ { "", "", "" }
+ , { "", pkg1, pkg1 }
+ , { "", pkg1, pkg2 }
+ , { pkg1, pkg1, pkg1 }
+ , { pkg1, pkg1, pkg2 }
+ , { pkg1, pkg2, pkg1 }
+ , { pkg1, pkg2, pkg2 }
+ };
+
+ String [] header = new String[] {
+ String.format("%30s %45s %20s", "Method access modifiers", "Call site location", "Status")
+ , String.format("%4s %-12s %-12s %-12s %7s %7s %7s %7s %7s %7s"
+ , " # "
+ , "A.m()"
+ , "B.m()"
+ , "C.m()"
+ , " A "
+ , "pkgA "
+ , " B "
+ , " pkgB"
+ , " C "
+ , "pkgC "
+ )
+ , "-------------------------------------------------------------------------------------------------"
+ };
+
+ for (String str : header) {
+ System.out.println(str);
+ }
+
+ for (String[] pkgSet : packageSets) {
+ String packageA = pkgSet[0];
+ String packageB = pkgSet[1];
+ String packageC = pkgSet[2];
+
+ String classNameA = packageA + "A";
+ String classNameB = packageB + "B";
+ String classNameC = packageC + "C";
+
+ String staticCallerParam = classNameA;
+
+ // For all possible access modifier combinations
+ for (AccessType accessA : AccessType.values()) {
+ for (AccessType accessB : AccessType.values()) {
+ for (AccessType accessC : AccessType.values()) {
+
+ if (accessA == AccessType.UNDEF) {
+ continue;
+ }
+
+ for (int I = 0; I < 4; I++) {
+ boolean isAbstractA = ((I & 1) != 0);
+ boolean isAbstractB = ((I & 2) != 0);
+
+ Map<String, byte[]> classes = new HashMap<String, byte[]>();
+
+ // Generate class A
+ classes.put(
+ classNameA
+ , new ClassGenerator( classNameA
+ , "java.lang.Object"
+ , ACC_PUBLIC | (isAbstractA ? ACC_ABSTRACT : 0))
+ .addTargetMethod( accessA
+ , (isAbstractA ? ACC_ABSTRACT : 0))
+ .addCaller(staticCallerParam)
+ .getClassFile()
+ );
+
+ // Generate class B
+ classes.put(
+ classNameB
+ , new ClassGenerator( classNameB
+ , classNameA
+ , ACC_PUBLIC | (isAbstractB ? ACC_ABSTRACT : 0))
+ .addTargetMethod( accessB
+ , (isAbstractB ? ACC_ABSTRACT : 0))
+ .addCaller(staticCallerParam)
+ .getClassFile()
+ );
+
+ // Generate class C
+ classes.put(
+ classNameC
+ , new ClassGenerator(classNameC, classNameB)
+ .addTargetMethod(accessC)
+ .addCaller(staticCallerParam)
+ .getClassFile()
+ );
+
+ // Generate package callers
+ for (String pkg : packages) {
+ classes.put(
+ pkg+"Caller"
+ , new ClassGenerator(pkg+"Caller")
+ .addCaller(staticCallerParam)
+ .getClassFile()
+ );
+ }
+
+ String[] callSites = new String[] {
+ classNameA
+ , packageA+"Caller"
+ , classNameB
+ , packageB+"Caller"
+ , classNameC
+ , packageC+"Caller"
+ };
+
+
+ String caseDescription =
+ String.format("%-12s %-12s %-12s| "
+ , (isAbstractA ? "! " : " ") + classNameA + " " + accessA
+ , (isAbstractB ? "! " : " ") + classNameB + " " + accessB
+ , classNameC + " " + accessC
+ );
+
+ boolean result = exec(classes, caseDescription, staticCallerParam, classNameC, callSites);
+ isPassed = isPassed && result;
+ }
+ }
+ }
+ }
+ }
+
+ // Print footer
+ for (int i = header.length-1; i >= 0; i--) {
+ System.out.println(header[i]);
+ }
+
+ if (executeTests) {
+ System.out.printf("\nEXECUTION STATUS: %s\n", (isPassed? "PASSED" : "FAILED"));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/invokevirtualTests.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8224137
+ * @summary Run invokevirtual invocation tests
+ * @library /test/lib
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.misc
+ * @compile shared/AbstractGenerator.java shared/AccessCheck.java shared/AccessType.java
+ * shared/Caller.java shared/ExecutorGenerator.java shared/Utils.java
+ * shared/ByteArrayClassLoader.java shared/Checker.java shared/GenericClassGenerator.java
+ * @compile invokevirtual/Checker.java invokevirtual/ClassGenerator.java invokevirtual/Generator.java
+ *
+ * @run main/othervm/timeout=1800 invokevirtualTests
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class invokevirtualTests {
+
+ public static void runTest(String classFileVersion, String option) throws Exception {
+ System.out.println("\ninvokevirtual invocation tests, option: " + option +
+ ", class file version: " + classFileVersion);
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(false, "-Xmx128M", option,
+ "invokevirtual.Generator", "--classfile_version=" + classFileVersion);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ try {
+ output.shouldContain("EXECUTION STATUS: PASSED");
+ output.shouldHaveExitValue(0);
+ } catch (Throwable e) {
+ System.out.println(
+ "\nNote that an entry such as 'B.m/C.m' in the failure chart means that" +
+ " the test case failed because method B.m was invoked but the test " +
+ "expected method C.m to be invoked. Similarly, a result such as 'AME/C.m'" +
+ " means that an AbstractMethodError exception was thrown but the test" +
+ " case expected method C.m to be invoked.");
+ System.out.println(
+ "\nAlso note that passing --dump to invokevirtual.Generator will" +
+ " dump the generated classes (for debugging purposes).\n");
+ System.exit(1);
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ // Get current major class file version and test with it.
+ byte klassbuf[] = InMemoryJavaCompiler.compile("blah", "public class blah { }");
+ int major_version = klassbuf[6] << 8 | klassbuf[7];
+ runTest(String.valueOf(major_version), "-Xint");
+// Uncomment the below test once JDK-8226588 is fixed
+// runTest(String.valueOf(major_version), "-Xcomp");
+
+ // Test old class file version.
+ runTest("51", "-Xint"); // JDK-7
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/AbstractGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ *
+ */
+public abstract class AbstractGenerator {
+ protected final boolean dumpClasses;
+ protected final boolean executeTests;
+ private static int testNum = 0;
+
+ protected AbstractGenerator(String[] args) {
+ List<String> params = new ArrayList<String>(Arrays.asList(args));
+
+ if (params.contains("--help")) {
+ Utils.printHelp();
+ System.exit(0);
+ }
+
+ dumpClasses = params.contains("--dump");
+ executeTests = !params.contains("--noexecute");
+
+ params.remove("--dump");
+ params.remove("--noexecute");
+
+ Utils.init(params);
+ }
+
+ /*******************************************************************/
+ public static void writeToFile(File dir, Map<String, byte[]> classes) {
+ for (String name : classes.keySet()) {
+ try {
+ writeToFile(dir, name, classes.get(name));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /*******************************************************************/
+ public static void writeToFile(File dir, String fullName, byte[] classBytecode) {
+ if (!dir.isDirectory()) {
+ throw new RuntimeException("Invalid parameter: dir doesn't point to an existing directory");
+ }
+
+ File classFile =
+ new File(
+ dir.getPath() + File.separator
+ + fullName.replaceAll("\\.", File.separator)
+ + ".class"
+ );
+
+ classFile.getParentFile().mkdirs();
+
+ try {
+ FileOutputStream fos = new FileOutputStream(classFile);
+ try {
+ fos.write(classBytecode);
+ } finally {
+ fos.close();
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected boolean exec(Map<String, byte[]> classes, String description, String calleeClassName, String classNameC, String[] callSites) throws ClassNotFoundException {
+ boolean isPassed = true;
+
+ testNum++;
+
+ String caseDescription = String.format("%4d| %s", testNum, description);
+
+ // Create test executor for a single case
+ classes.put(
+ ExecutorGenerator.className
+ , new ExecutorGenerator(
+ caseDescription
+ , calleeClassName
+ , classNameC
+ ).generateExecutor(callSites)
+ );
+
+ // Dump generated set to disk, if needed
+ if (dumpClasses) {
+ File dir = new File("classes" + File.separator + String.format("%04d", testNum));
+ dir.mkdirs();
+ writeToFile(dir, classes);
+ }
+
+ ByteArrayClassLoader loader = new ByteArrayClassLoader(classes);
+
+ Class paramClass;
+ Class targetClass;
+ Checker checker;
+
+ try {
+ paramClass = loader.loadClass(calleeClassName);
+ targetClass = loader.loadClass(classNameC);
+
+ checker = getChecker(paramClass, targetClass);
+ } catch (Throwable e) {
+ String result = Checker.abbreviateResult(e.getClass().getName());
+
+ System.out.printf(caseDescription);
+
+ for (String site : callSites) {
+ System.out.printf(" %7s", result);
+ }
+
+ System.out.println("");
+
+ return true;
+ }
+
+ if (executeTests) {
+ // Check runtime behavior
+ Caller caller = new Caller(loader, checker, paramClass, targetClass);
+ boolean printedCaseDes = false;
+ for (String site : callSites) {
+ String callResult = caller.call(site);
+
+ if (!caller.isPassed()) {
+ isPassed = false;
+ if (!printedCaseDes) {
+ System.out.printf(caseDescription);
+ printedCaseDes = true;
+ }
+ System.out.printf(" %7s", callResult);
+ }
+ }
+ if (!caller.isPassed()) {
+ System.out.println(" | FAILED");
+ }
+ } else {
+ for (String site : callSites) {
+ String result = checker.check(loader.loadClass(site));
+ System.out.printf(" %7s", Checker.abbreviateResult(result));
+ }
+ }
+
+ return isPassed;
+ }
+
+ protected abstract Checker getChecker(Class paramClass, Class targetClass);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/AccessCheck.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+/**
+ *
+ * @author vi158347
+ */
+public class AccessCheck {
+ public static boolean isAbstract(int access) {
+ return (access & ACC_ABSTRACT) != 0;
+ }
+
+ public static boolean isPublic(int access) {
+ return (access & ACC_PUBLIC) != 0;
+ }
+
+ public static boolean isProtected(int access) {
+ return (access & ACC_PROTECTED) != 0;
+ }
+
+ public static boolean isPackagePrivate(int access) {
+ return !isPublic(access) && !isProtected(access) && !isPrivate(access);
+ }
+
+ public static boolean isPrivate(int access) {
+ return (access & ACC_PRIVATE) != 0;
+ }
+
+ public static boolean isInterface(int access) {
+ return (access & ACC_INTERFACE) != 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/AccessType.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+public enum AccessType {
+ PUBLIC ("PUB") { public int value() { return ACC_PUBLIC; } }
+ , PROTECTED ("PROT") { public int value() { return ACC_PROTECTED; } }
+ , PACKAGE_PRIVATE ("PP") { public int value() { return 0; } }
+ , PRIVATE ("PRIV") { public int value() { return ACC_PRIVATE; } }
+ , UNDEF ("UNDEF") { public int value() { return -1; } }
+ ;
+
+ private String name;
+
+ AccessType(String name) {
+ this.name = name;
+ }
+
+ public abstract int value();
+
+ public String toString() {
+ return name;
+ }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/ByteArrayClassLoader.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/*******************************************************************/
+// Class loader which has local class file storage in memory
+/*******************************************************************/
+
+public class ByteArrayClassLoader extends ClassLoader {
+ private Map<String, byte[]> classes;
+
+ public ByteArrayClassLoader() {
+ classes = new HashMap<String, byte[]>();
+ }
+
+ public ByteArrayClassLoader(Map<String, byte[]> classes) {
+ this.classes = classes;
+ }
+
+ public void appendClass(String name, byte[] classFile) {
+ classes.put(name, classFile);
+ }
+
+ public Class findClass (String name) throws ClassNotFoundException {
+ if (classes.containsKey(name)) {
+ byte[] classData = classes.get(name);
+ return defineClass(name, classData, 0, classData.length);
+ } else {
+ throw new ClassNotFoundException("Can't find requested class: " + name);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/Caller.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import java.lang.reflect.InvocationTargetException;
+
+/*******************************************************************/
+// Invoke different target method callers
+/*******************************************************************/
+
+public class Caller {
+ private ClassLoader loader;
+ private Class paramClass;
+ private Class targetClass;
+ private boolean passed = true;
+ private Checker checker;
+
+ public Caller(ClassLoader loader, Checker checker,
+ Class paramClass, Class targetClass) {
+ this.loader = loader;
+ this.paramClass = paramClass;
+ this.targetClass = targetClass;
+ this.checker = checker;
+ }
+
+ public boolean isPassed() {
+ return passed;
+ }
+
+ public String call(String invoker) {
+ try {
+ Class clazz = loader.loadClass(invoker);
+
+ String expectedBehavior = checker.check(clazz);
+
+ String result = null;
+ Throwable exc = null;
+ try {
+ java.lang.reflect.Method m = clazz.getDeclaredMethod("call", paramClass);
+ result = (String) m.invoke(null, targetClass.newInstance());
+ } catch (InvocationTargetException e) {
+ exc = e.getCause();
+ } catch (Throwable e) {
+ exc = e;
+ }
+
+ if (result == null) {
+ if (exc != null) {
+ result = exc.getClass().getName();
+ } else {
+ result = "null";
+ }
+ }
+
+ if (!(result.equals(expectedBehavior) || "".equals(expectedBehavior)) ) {
+ passed = false;
+ result = String.format("%s/%s", result, expectedBehavior);
+ }
+
+ return Checker.abbreviateResult(result);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/Checker.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public abstract class Checker {
+ protected Class staticTargetClass;
+ protected Class dynamicTargetClass;
+ protected String methodName;
+
+ public abstract String check (Class callSite);
+
+ public Checker(Class staticTargetClass, Class dynamicTargetClass) {
+ if (!staticTargetClass.isAssignableFrom(dynamicTargetClass)) {
+ throw new RuntimeException("Dynamic target class should be a subclass of the static target class.");
+ }
+
+ // **********************************************
+ // NB!!! All classes are assumed to be PUBLIC !!!
+ // **********************************************
+ Class klass = dynamicTargetClass;
+ while (klass != Object.class) {
+ if (!Modifier.isPublic(klass.getModifiers())) {
+ throw new AssertionError("Class "+klass.getName()+" isn't public.");
+ }
+
+ klass = klass.getSuperclass();
+ }
+
+ this.methodName = Utils.TARGET_METHOD_NAME;
+ this.staticTargetClass = staticTargetClass;
+ this.dynamicTargetClass = dynamicTargetClass;
+ }
+
+ protected Method getMethodInHierarchy (Class klass) {
+ return getMethodInHierarchy(klass, methodName);
+ }
+
+ protected Method getMethodInHierarchy (Class klass, String name) {
+ while (klass != null) {
+ Method method = getDeclaredMethod (klass, name);
+
+ if ( method != null) {
+// TODO: why doesn't this check work in VM?
+// int modifiers = method.getModifiers();
+//
+// if (Modifier.isPrivate(modifiers)) {
+// if (klass == initialClass) {
+// return method;
+// }
+// } else {
+// return method;
+// }
+ return method;
+ }
+ klass = klass.getSuperclass();
+ }
+
+ return null;
+ }
+
+ protected Method getMethod (Class klass) {
+ return getMethod (klass, methodName);
+ }
+
+ protected Method getDeclaredMethod (Class klass) {
+ return getDeclaredMethod (klass, methodName);
+ }
+
+ static protected Method getMethod (Class klass, String name) {
+ return findMethod (klass.getMethods(), name);
+ }
+
+ static protected Method getDeclaredMethod (Class klass, String name) {
+ return findMethod (klass.getDeclaredMethods(), name);
+ }
+
+ static protected Method findMethod (Method[] methods, String name) {
+ for (Method method : methods) {
+ if (name.equals(method.getName())) {
+ return method;
+ }
+ }
+
+ return null;
+ }
+
+ static public String getClassPackageName(Class klass) {
+ String name = klass.getName();
+ return getClassPackageName(name);
+ }
+
+ static public String getClassPackageName(String name) {
+ int lastDotIndex = name.lastIndexOf('.');
+ if (lastDotIndex > -1) {
+ return name.substring(0, lastDotIndex);
+ } else {
+ return "";
+ }
+ }
+
+ public static String abbreviateResult(String result) {
+ // Abbreviate exception names
+ result = result.replaceAll("java.lang.NullPointerException", "NPE");
+ result = result.replaceAll("java.lang.IllegalAccessError", "IAE");
+ result = result.replaceAll("java.lang.IllegalAccessException", "IAExc");
+ result = result.replaceAll("java.lang.NoSuchMethodError", "NSME");
+ result = result.replaceAll("java.lang.AbstractMethodError", "AME");
+ result = result.replaceAll("java.lang.IncompatibleClassChangeError", "ICCE");
+ result = result.replaceAll("java.lang.VerifyError", "VE");
+ result = result.replaceAll("java.lang.ClassFormatError", "CFE");
+
+ return result;
+ }
+
+ // Check access possibility from particular call site
+ protected boolean checkAccess(Class klass, Class callerClass) {
+ int modifiers = klass.getModifiers();
+
+ return checkAccess(modifiers, klass, callerClass);
+ }
+
+ protected boolean checkAccess(Method m, Class callerClass) {
+ int modifiers = m.getModifiers();
+ Class declaringClass = m.getDeclaringClass();
+
+ return checkAccess(modifiers, declaringClass, callerClass);
+ }
+
+ protected boolean checkAccess(int modifiers, Class klass, Class callerClass) {
+ if ( Modifier.isPublic(modifiers) ) {
+ return true;
+ } else if ( Modifier.isProtected(modifiers) ) {
+ if (klass.isAssignableFrom(callerClass)) {
+ return true;
+ } else if (getClassPackageName(klass).equals(getClassPackageName(callerClass))) {
+ return true;
+ }
+ } else if ( Modifier.isPrivate(modifiers)) {
+ if (klass == callerClass) {
+ return true;
+ }
+ } else if (getClassPackageName(klass).equals(getClassPackageName(callerClass))) {
+ return true;
+ } else {
+ // if method isn't accessible, IllegalAccessException is thrown
+ return false;
+ }
+
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/ExecutorGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import static jdk.internal.org.objectweb.asm.ClassWriter.*;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+public class ExecutorGenerator {
+ public static final String className = Utils.getInternalName("Test");
+ private String caseDescription;
+ private String staticTargetName;
+ private String dynamicTargetName;
+
+ private String callerSignature;
+
+ public ExecutorGenerator(String caseDescription,
+ String staticTargetName,
+ String dynamicTargetName) {
+ this.caseDescription = caseDescription;
+ this.staticTargetName = Utils.getInternalName(staticTargetName);
+ this.dynamicTargetName = Utils.getInternalName(dynamicTargetName);
+ callerSignature = String.format("(L%s;)Ljava/lang/String;", this.staticTargetName);
+ }
+
+ public byte[] generateExecutor(String[] callSites) {
+ ClassWriter cw = new ClassWriter(COMPUTE_MAXS);
+
+ cw.visit(Utils.version, ACC_PUBLIC | (Utils.isACC_SUPER ? ACC_SUPER : 0), className, null, "java/lang/Object", null);
+
+ // Generate constructor
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitEnd();
+ mv.visitMaxs(0, 0);
+ }
+
+ // public static void main(String[] args) {
+ // new Test().run();
+ // }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, className);
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");
+ mv.visitMethodInsn(INVOKEVIRTUAL, className, "run", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitEnd();
+ mv.visitMaxs(0, 0);
+ }
+
+ // private String indent(String result) {
+ // while (result.length() < 8) {
+ // result = " "+result;
+ // }
+ // return result;
+ // }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "indent", "(Ljava/lang/String;)Ljava/lang/String;", null, null);
+ mv.visitCode();
+ Label l0 = new Label();
+ mv.visitLabel(l0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "length", "()I");
+ mv.visitIntInsn(BIPUSH, 8);
+ Label l1 = new Label();
+ mv.visitJumpInsn(IF_ICMPGE, l1);
+ mv.visitTypeInsn(NEW, "java/lang/StringBuffer");
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer", "<init>", "()V");
+ mv.visitLdcInsn(" ");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "toString", "()Ljava/lang/String;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitJumpInsn(GOTO, l0);
+ mv.visitLabel(l1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ mv.visitMaxs(0, 0);
+ }
+
+ //private String abbr(String result) {
+ // result = result.replaceAll("java.lang.NullPointerException", "NPE");
+ // result = result.replaceAll("java.lang.IllegalAccessError", "IAE");
+ // result = result.replaceAll("java.lang.IllegalAccessException", "IAExc");
+ // result = result.replaceAll("java.lang.NoSuchMethodError", "NSME");
+ // result = result.replaceAll("java.lang.AbstractMethodError", "AME");
+ // result = result.replaceAll("java.lang.IncompatibleClassChangeError", "ICCE");
+ //
+ // return result;
+ //}
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "abbr", "(Ljava/lang/String;)Ljava/lang/String;", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitLdcInsn("java.lang.NullPointerException");
+ mv.visitLdcInsn("NPE");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitLdcInsn("java.lang.IllegalAccessError");
+ mv.visitLdcInsn("IAE");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitLdcInsn("java.lang.IllegalAccessException");
+ mv.visitLdcInsn("IAExc");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitLdcInsn("java.lang.NoSuchMethodError");
+ mv.visitLdcInsn("NSME");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitLdcInsn("java.lang.AbstractMethodError");
+ mv.visitLdcInsn("AME");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitLdcInsn("java.lang.IncompatibleClassChangeError");
+ mv.visitLdcInsn("ICCE");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ mv.visitMaxs(0, 0);
+ }
+
+ // Generate execution method
+ // public void run() {
+ // System.out.print("2048| ! a.A PUB ! b.B PP a.C PROT |");
+ //
+ // C object = new C();
+ //
+ // try {
+ // System.out.print(indent(A.call(object)));
+ // } catch (Throwable e) {
+ // System.out.print(indent(abbr(e.getClass().getName())));
+ // }
+ //
+ // ...
+ //
+ // System.out.println();
+ // }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
+ mv.visitCode();
+
+ // Generate try/catch blocks
+ Label[][] tryCatchLabels = new Label[callSites.length][3];
+ for (int I = 0; I < tryCatchLabels.length; I++) {
+ Label[] labels = tryCatchLabels[I];
+ for (int K = 0; K < labels.length; K++) {
+ labels[K] = new Label();
+ }
+
+ mv.visitTryCatchBlock(labels[0], labels[1], labels[2], "java/lang/Throwable");
+ }
+
+ // System.out.print("2048| ! a.A PUB ! b.B PP a.C PROT |");
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitLdcInsn(caseDescription);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V");
+
+ // C object = new C();
+ mv.visitTypeInsn(NEW, dynamicTargetName);
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKESPECIAL, dynamicTargetName, "<init>", "()V");
+ mv.visitVarInsn(ASTORE, 1);
+
+// for (String site: callSites) {
+ // System.out.print(indent(A.call(object)));
+// mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+// mv.visitVarInsn(ALOAD, 0);
+// mv.visitVarInsn(ALOAD, 1);
+// mv.visitMethodInsn(INVOKESTATIC, AbstractGenerator.getInternalName(site), "call", callerSignature);
+// mv.visitMethodInsn(INVOKESPECIAL, className, "indent", "(Ljava/lang/String;)Ljava/lang/String;");
+// mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V");
+// }
+
+ Label returnLabel = new Label();
+ for (int I = 0; I < callSites.length; I++) {
+ String site = callSites[I];
+ Label[] l = tryCatchLabels[I];
+
+ Label nextBlock = (I+1 < callSites.length ? tryCatchLabels[I+1][0] : returnLabel);
+
+ mv.visitLabel(l[0]);
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitMethodInsn(INVOKESTATIC, Utils.getInternalName(site), "call", callerSignature);
+ mv.visitMethodInsn(INVOKESPECIAL, className, "indent", "(Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V");
+ mv.visitLabel(l[1]);
+ mv.visitJumpInsn(GOTO, nextBlock);
+ mv.visitLabel(l[2]);
+ mv.visitVarInsn(ASTORE, 2);
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;");
+ mv.visitMethodInsn(INVOKESPECIAL, className, "abbr", "(Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitMethodInsn(INVOKESPECIAL, className, "indent", "(Ljava/lang/String;)Ljava/lang/String;");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V");
+ }
+ mv.visitLabel(returnLabel);
+
+ // System.out.println();
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "()V");
+ mv.visitInsn(RETURN);
+
+ mv.visitEnd();
+ mv.visitMaxs(0, 0);
+ }
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/GenericClassGenerator.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
+import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import static shared.AccessCheck.*;
+
+public class GenericClassGenerator<T extends GenericClassGenerator> {
+ private static final String targetMethodName = Utils.TARGET_METHOD_NAME;
+
+ private int flags = 0;
+ private ClassWriter writer;
+ private String fullClassName = null;
+ private String parentClassName = null;
+
+ /*******************************************************************/
+ public GenericClassGenerator(String fullClassName) {
+ this(fullClassName, "java/lang/Object");
+ }
+
+ /*******************************************************************/
+ public GenericClassGenerator(String fullClassName, String parentClassName ) {
+ this(fullClassName, parentClassName, ACC_PUBLIC);
+ }
+
+ /*******************************************************************/
+ public GenericClassGenerator(String fullClassName, String parentClassName, int flags) {
+ this(fullClassName, parentClassName, flags, new String[0]);
+ }
+
+ /*******************************************************************/
+ public GenericClassGenerator(String fullClassName, String parentClassName, int flags, String[] implementedInterfaces) {
+ writer = new ClassWriter(COMPUTE_FRAMES | COMPUTE_MAXS);
+
+ this.fullClassName = fullClassName;
+ this.flags = flags;
+
+ // Construct simple class
+ if (parentClassName != null) {
+ this.parentClassName = getInternalName(parentClassName);
+ } else {
+ this.parentClassName = "java/lang/Object";
+ }
+
+ String parent = this.parentClassName;
+ String name = getInternalName(fullClassName);
+
+ if (Utils.isACC_SUPER) {
+ flags = flags | ACC_SUPER;
+ }
+
+ writer.visit(Utils.version, flags, name, null, parent, implementedInterfaces);
+
+ // Add constructor
+ if ( !isInterface(flags) ) {
+ MethodVisitor m =
+ writer.visitMethod(
+ ACC_PUBLIC
+ , "<init>"
+ , "()V"
+ , null
+ , null
+ );
+
+ m.visitCode();
+ m.visitVarInsn(ALOAD, 0);
+ m.visitMethodInsn(
+ INVOKESPECIAL
+ , getInternalName(parent)
+ , "<init>"
+ , "()V"
+ );
+ m.visitInsn(RETURN);
+ m.visitEnd();
+ m.visitMaxs(0,0);
+ }
+ }
+
+ /*******************************************************************/
+ protected static String getInternalName(String fullClassName) {
+ return fullClassName.replaceAll("\\.", "/");
+ }
+
+ /*******************************************************************/
+ public T addTargetConstructor(AccessType access) {
+ // AccessType.UNDEF means that the target method isn't defined, so do nothing
+ if (access == AccessType.UNDEF || isInterface(flags) ) {
+ return (T)this;
+ }
+
+ // Add target constructor
+ int methodAccessType = access.value();
+
+ MethodVisitor m =
+ writer.visitMethod(
+ methodAccessType
+ , "<init>"
+ , "(I)V"
+ , null
+ , null
+ );
+
+ // Add a call to parent constructor
+ m.visitCode();
+ m.visitVarInsn(ALOAD, 0);
+ m.visitMethodInsn(
+ INVOKESPECIAL
+ , getInternalName(parentClassName)
+ , "<init>"
+ , "()V"
+ );
+
+ // Add result reporting
+ String shortName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
+ m.visitLdcInsn(shortName+".<init>");
+ m.visitFieldInsn(
+ PUTSTATIC
+ , "Result"
+ , "value"
+ , "Ljava/lang/String;"
+ );
+
+ m.visitInsn(RETURN);
+ m.visitEnd();
+ m.visitMaxs(0,0);
+
+ return (T)this;
+
+ }
+
+ /*******************************************************************/
+ public T addTargetMethod(AccessType access) {
+ return addTargetMethod(access, 0);
+ }
+
+ /*******************************************************************/
+ public T addTargetMethod(AccessType access, int additionalFlags) {
+ // AccessType.UNDEF means that the target method isn't defined, so do nothing
+ if (access == AccessType.UNDEF) {
+ return (T)this;
+ }
+
+ // Add target method
+ int methodAccessType = access.value();
+ if ( isInterface(flags) || isAbstract(flags) ) {
+ methodAccessType |= ACC_ABSTRACT;
+ }
+
+ // Skip method declaration for abstract private case, which doesn't pass
+ // classfile verification stage
+ if ( isPrivate(methodAccessType) && isAbstract(methodAccessType) ) {
+ return (T)this;
+ }
+
+ MethodVisitor m =
+ writer.visitMethod(
+ methodAccessType | additionalFlags
+ , targetMethodName
+ , "()Ljava/lang/String;"
+ , null
+ , null
+ );
+
+ // Don't generate body if the method is abstract
+ if ( (methodAccessType & ACC_ABSTRACT) == 0 ) {
+ String shortName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
+
+ // Simply returns info about itself
+ m.visitCode();
+ m.visitLdcInsn(shortName+"."+targetMethodName);
+ m.visitInsn(ARETURN);
+ m.visitEnd();
+ m.visitMaxs(0,0);
+ }
+
+ return (T)this;
+ }
+
+ /*******************************************************************/
+ public T addField(int access, String name, String type) {
+ writer.visitField(
+ access
+ , name
+ , getInternalName(type)
+ , null
+ , null
+ )
+ .visitEnd();
+
+ return (T)this;
+ }
+
+ /*******************************************************************/
+ // Add target method call site into current class
+ public T addCaller(String targetClass, int callType) {
+ MethodVisitor m = writer.visitMethod(
+ ACC_PUBLIC | ACC_STATIC
+ , "call"
+ , String.format( "(L%s;)Ljava/lang/String;" , getInternalName(targetClass))
+ , null
+ , null
+ );
+
+ m.visitCode();
+ m.visitVarInsn(ALOAD, 0);
+ m.visitMethodInsn(
+ callType
+ , getInternalName(targetClass)
+ , targetMethodName
+ , "()Ljava/lang/String;"
+ );
+ m.visitInsn(ARETURN);
+ m.visitEnd();
+ m.visitMaxs(0,0);
+
+ return (T)this;
+ }
+
+ /*******************************************************************/
+ public byte[] getClassFile() {
+ writer.visitEnd();
+ return writer.toByteArray();
+ }
+
+ /*******************************************************************/
+ public String getFullClassName() {
+ return fullClassName;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/InvocationTests/shared/Utils.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package shared;
+
+import java.util.List;
+
+/**
+ * Just a set of constants
+ */
+public class Utils {
+ public static final String TARGET_METHOD_NAME = "m";
+ public static int version = 50;
+
+ public static boolean isACC_SUPER = false;
+
+ public static void init(List<String> args) {
+ for (String param : args) {
+ String name = "classfile_version";
+ String pattern = "--"+name+"=";
+ if (param.startsWith(pattern)) {
+ String value = param.substring(pattern.length());
+ int majorVersion = 50;
+ int minorVersion = 0;
+
+ try {
+ String[] versions = value.split(":");
+ if (versions.length > 2) {
+ throw new RuntimeException(String.format("Unknown %s value: %s", name, value));
+ }
+
+ try {
+ majorVersion = Integer.parseInt(versions[0]);
+ if (versions.length > 1) {
+ minorVersion = Integer.parseInt(versions[1]);
+ }
+ } catch(Exception e) {
+ throw new RuntimeException(String.format("Can't parse %s value: '%s'", name, value));
+ }
+ } catch (Exception e) {
+ System.out.println("ERROR: "+e.getMessage());
+ }
+
+ version = majorVersion + (minorVersion << 16);
+
+ System.out.printf("INFO: Class file version: major: %d; minor: %d\n", majorVersion, minorVersion);
+
+ if (majorVersion < 49 && !args.contains("--no_acc_super")) {
+ isACC_SUPER = true;
+ System.out.printf("INFO: Enabling ACC_SUPER flag for major: %d\nTo disable it, specify --no_acc_super option.\n", majorVersion, minorVersion);
+ }
+ } else if (param.equals("--no_acc_super")){
+ System.out.println("INFO: ACC_SUPER flag is disabled");
+ isACC_SUPER = false;
+ } else if (param.equals("--acc_super")){
+ isACC_SUPER = true;
+ } else {
+ System.out.println("ERROR: Unknown option: "+param);
+ printHelp();
+ System.exit(1);
+ }
+ }
+ }
+
+ public static void printHelp() {
+ System.out.println(
+ "Supported parameters:\n"
+ + "\t--classfile_version=major_version[:minor_version]\n"
+ + "\t\t- specify class file version for generated classes\n"
+ + "\t--no_acc_super\n"
+ + "\t\t- don't add ACC_SUPER flag into generated classes\n"
+ + "\t--acc_super\n"
+ + "\t\t- force ACC_SUPER flag in generated classes\n"
+ + "\t--dump\n"
+ + "\t\t- dump generated classes\n"
+ + "\t--noexecute\n"
+ + "\t\t- print only expected results, don't execute tests\n"
+ );
+ }
+
+ /*******************************************************************/
+ public static String getInternalName(String s) {
+ return s.replaceAll("\\.", "/");
+ }
+
+}
--- a/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/SysDictCrash.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,22 @@
"-Xshare:dump",
"-showversion", "-Xlog:cds,cds+hashtables"));
- TestCommon.checkDump(TestCommon.executeAndLog(dumpPb, "dump"));
+ boolean continueTest = true;
+ OutputAnalyzer output = TestCommon.executeAndLog(dumpPb, "dump");
+ try {
+ TestCommon.checkDump(output);
+ } catch (java.lang.RuntimeException re) {
+ if (!output.getStdout().contains("UseCompressedOops and UseCompressedClassPointers have been disabled due to")) {
+ throw re;
+ } else {
+ System.out.println("Shared archive was not created due to UseCompressedOops and UseCompressedClassPointers have been disabled.");
+ continueTest = false;
+ }
+ }
+
+ if (!continueTest) {
+ return;
+ }
ProcessBuilder runPb = ProcessTools.createJavaProcessBuilder(true,
TestCommon.concat(vmOptionsPrefix,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/access_test/pkg1/MethodTypeDescriptorAccessTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8226709
+ * @summary MethodTypeDesc::resolveConstantDesc needs access check per the specification
+ * @compile ../pkg2/PublicClass.java ../pkg2/NonPublicClass.java
+ * @run main pkg1.MethodTypeDescriptorAccessTest
+ */
+
+package pkg1;
+
+import java.lang.invoke.*;
+import java.lang.invoke.MethodType;
+import java.lang.constant.*;
+
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodHandles.Lookup.*;
+import static java.lang.invoke.MethodType.*;
+
+public class MethodTypeDescriptorAccessTest {
+ public static void main(String... args) throws Throwable {
+ new MethodTypeDescriptorAccessTest().test();
+ }
+
+ void test() {
+ Lookup selfLookup = MethodHandles.lookup();
+ //first test PublicClass
+ String descriptorpub = "(Lpkg2/PublicClass;)Lpkg2/PublicClass;";
+ MethodTypeDesc mtdpub = MethodTypeDesc.ofDescriptor(descriptorpub);
+ checkValidAccess(mtdpub, selfLookup);
+
+ // test NonPublicClass in the return type
+ String descriptornp = "()Lpkg2/NonPublicClass;";
+ MethodTypeDesc mtdnp = MethodTypeDesc.ofDescriptor(descriptornp);
+ checkInvalidAccess(mtdnp, selfLookup);
+
+ // test NonPublicClass in the parameters
+ descriptornp = "(Lpkg2/NonPublicClass;)I";
+ mtdnp = MethodTypeDesc.ofDescriptor(descriptornp);
+ checkInvalidAccess(mtdnp, selfLookup);
+
+ MethodType mt = MethodType.fromMethodDescriptorString("(Lpkg2/NonPublicClass;)I", selfLookup.lookupClass().getClassLoader());
+ }
+
+ private void checkValidAccess(MethodTypeDesc mtd, Lookup lookup) {
+ try {
+ MethodType mt = (MethodType)mtd.resolveConstantDesc(lookup);
+ } catch (ReflectiveOperationException unexpected) {
+ throw new Error("resolveConstantDesc() threw ReflectiveOperationException unexpectedly with cause " +
+ unexpected.getCause() + " for " + mtd);
+ }
+ }
+
+ private void checkInvalidAccess(MethodTypeDesc mtd, Lookup lookup) {
+ try {
+ MethodType mt = (MethodType)mtd.resolveConstantDesc(lookup);
+ throw new Error("resolveConstantDesc() succeeded unexpectedly " + mtd);
+ } catch (ReflectiveOperationException expected) {
+ if (expected.getClass() != IllegalAccessException.class) {
+ throw new Error("resolveConstantDesc() threw unexpected ReflectiveOperationException with cause " +
+ expected.getCause() + " for " + mtd);
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/access_test/pkg2/NonPublicClass.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg2;
+
+class NonPublicClass {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/constant/access_test/pkg2/PublicClass.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg2;
+
+public class PublicClass {}
--- a/test/jdk/java/net/Socket/SetSoLinger.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/jdk/java/net/Socket/SetSoLinger.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
* @summary Test Socket.setSoLinger
* @run main SetSoLinger
* @run main/othervm -Djava.net.preferIPv4Stack=true SetSoLinger
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true SetSoLinger
*/
import java.net.*;
@@ -41,7 +42,10 @@
int value;
InetAddress addr = InetAddress.getLocalHost();
- ServerSocket ss = new ServerSocket(0);
+ ServerSocket ss = new ServerSocket();
+
+ InetSocketAddress socketAddress = new InetSocketAddress(addr, 0);
+ ss.bind(socketAddress);
int port = ss.getLocalPort();
Socket s = new Socket(addr, port);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/LookAndFeel/SystemLookAndFeel/SystemLookAndFeelTest.java Fri Jun 28 14:36:42 2019 +0530
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @bug 8226783
+ * @key headful
+ * @summary Verify System L&F
+ */
+
+/*
+ * Verify the System LAF is what we expect based on platform and,
+ * in at least one case, the desktop environment.
+ * Since changes to the system LAF are a once in a blue moon event,
+ * this test is useful to tell us of unexpected problems.
+ * Note: this test must be run in a headful environment
+ * since otherwise a system LAF may not be available.
+ */
+
+public class SystemLookAndFeelTest {
+
+ public static void main(String[] args) {
+
+ String laf = javax.swing.UIManager.getSystemLookAndFeelClassName();
+ String os = System.getProperty("os.name").toLowerCase();
+ System.out.println("OS is " + os);
+ System.out.println("Reported System LAF is " + laf);
+
+ String expLAF = null;
+ if (os.contains("windows")) {
+ expLAF = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
+ } else if (os.contains("macos")) {
+ expLAF = "com.apple.laf.AquaLookAndFeel";
+ } else if (os.contains("linux") || os.contains("sunos")) {
+ /*
+ * The implementation keys off the following desktop setting to
+ * decide if GTK is an appropriate system L&F.
+ * In its absence, there probably isn't support for the GTK L&F
+ * anyway. It does not tell us if the GTK libraries are available
+ * but they really should be if this is a gnome session.
+ * If it proves necessary the test can perhaps be updated to see
+ * if the GTK LAF is listed as installed and can be instantiated.
+ */
+ String gnome = System.getenv("GNOME_DESKTOP_SESSION_ID");
+ System.out.println("Gnome desktop session ID is " + gnome);
+ if (gnome != null) {
+ expLAF = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
+ } else if (os.contains("linux")) {
+ expLAF = "javax.swing.plaf.metal.MetalLookAndFeel";
+ } else if (os.contains("sunos")) {
+ expLAF = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
+ }
+ }
+ System.out.println("Expected System LAF is " + expLAF);
+ if (expLAF == null) {
+ System.out.println("No match for expected LAF, unknown OS ?");
+ return;
+ }
+ if (!(laf.equals(expLAF))) {
+ throw new RuntimeException("LAF not as expected");
+ }
+ }
+}
--- a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java Fri Jun 28 14:36:42 2019 +0530
@@ -100,20 +100,30 @@
"CMRefRoots",
"WaitForStrongCLD",
"WeakCLDRoots",
- "UpdateRS",
- "ScanHCC",
- "ScanRS",
+ "MergeHCC",
+ "MergeRS",
+ "MergeLB",
+ "ScanHR",
"CodeRoots",
"ObjCopy",
"Termination",
"StringDedupQueueFixup",
"StringDedupTableFixup",
"RedirtyCards",
- // "PreserveCMReferents",
"NonYoungFreeCSet",
"YoungFreeCSet"
);
+ // Some GC phases may or may not occur depending on environment. Filter them out
+ // since we can not reliably guarantee that they occur (or not).
+ Set<String> optPhases = of(
+ "OptScanHR",
+ "OptMergeRS",
+ "OptCodeRoots",
+ "OptObjCopy"
+ );
+ usedPhases.removeAll(optPhases);
+
assertTrue(usedPhases.equals(allPhases), "Compare events expected and received"
+ ", Not found phases: " + allPhases.stream().filter(p -> !usedPhases.contains(p)).collect(joining(", "))
+ ", Not expected phases: " + usedPhases.stream().filter(p -> !allPhases.contains(p)).collect(joining(", ")));
--- a/test/jdk/sun/net/www/protocol/http/AsyncDisconnect.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/AsyncDisconnect.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,18 +24,21 @@
/*
* @test
* @bug 6358532
+ * @library /test/lib
* @modules jdk.httpserver
* @run main/othervm AsyncDisconnect
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true AsyncDisconnect
* @summary HttpURLConnection.disconnect doesn't really do the job
*/
import java.net.*;
-import java.util.*;
import java.io.*;
import com.sun.net.httpserver.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
+import jdk.test.lib.net.URIBuilder;
+
public class AsyncDisconnect implements Runnable
{
com.sun.net.httpserver.HttpServer httpServer;
@@ -43,27 +46,30 @@
ExecutorService executorService;
HttpURLConnection uc;
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
new AsyncDisconnect();
}
- public AsyncDisconnect() {
- try {
- startHttpServer();
- doClient();
- } catch (IOException ioe) {
- System.err.println(ioe);
- }
+ public AsyncDisconnect() throws Exception {
+ startHttpServer();
+ doClient();
}
- void doClient() {
+ void doClient() throws Exception {
+ Thread t = new Thread(this);
+
try {
InetSocketAddress address = httpServer.getAddress();
- URL url = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test/");
- uc = (HttpURLConnection)url.openConnection();
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .host(address.getAddress())
+ .port(address.getPort())
+ .path("/test/")
+ .toURL();
+ uc = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
// create a thread that will disconnect the connection
- (new Thread(this)).start();
+ t.start();
uc.getInputStream();
@@ -73,11 +79,11 @@
} catch (SocketException se) {
// this is what we expect to happen and is OK.
//System.out.println(se);
- } catch (IOException e) {
- e.printStackTrace();
} finally {
httpServer.stop(1);
+ t.join();
executorService.shutdown();
+
}
}
@@ -93,7 +99,9 @@
* Http Server
*/
public void startHttpServer() throws IOException {
- httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ InetSocketAddress address = new InetSocketAddress(loopback, 0);
+ httpServer = com.sun.net.httpserver.HttpServer.create(address, 0);
httpHandler = new MyHandler();
HttpContext ctx = httpServer.createContext("/test/", httpHandler);
--- a/test/jdk/sun/net/www/protocol/http/B6641309.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/B6641309.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,10 @@
* @test
* @bug 6641309
* @modules jdk.httpserver
- * @summary Wrong Cookie separator used in HttpURLConnection
+ * @library /test/lib
+ * @run main/othervm B6641309
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B6641309
+ * @summary Wrong Cookie separator used in HttpURLConnection B6641309
*/
import java.net.*;
@@ -35,65 +38,65 @@
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
+import jdk.test.lib.net.URIBuilder;
+
public class B6641309
{
com.sun.net.httpserver.HttpServer httpServer;
ExecutorService executorService;
- public static void main(String[] args)
- {
+ public static void main(String[] args) throws Exception {
new B6641309();
}
- public B6641309()
- {
- try {
- startHttpServer();
- doClient();
- } catch (IOException ioe) {
- System.err.println(ioe);
- }
+ public B6641309() throws Exception {
+ startHttpServer();
+ doClient();
}
- void doClient() {
+ void doClient() throws Exception {
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
- try {
- InetSocketAddress address = httpServer.getAddress();
+ ProxySelector.setDefault(ProxySelector.of(null));
+
+ InetSocketAddress address = httpServer.getAddress();
- // GET Request
- URL url = new URL("http://localhost:" + address.getPort() + "/test/");
- CookieHandler ch = CookieHandler.getDefault();
- Map<String,List<String>> header = new HashMap<String,List<String>>();
- List<String> values = new LinkedList<String>();
- values.add("Test1Cookie=TEST1; path=/test/");
- values.add("Test2Cookie=TEST2; path=/test/");
- header.put("Set-Cookie", values);
+ // GET Request
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .host(address.getAddress())
+ .port(address.getPort())
+ .path("/test/")
+ .toURL();
- // preload the CookieHandler with a cookie for our URL
- // so that it will be sent during the first request
- ch.put(url.toURI(), header);
- HttpURLConnection uc = (HttpURLConnection)url.openConnection();
- int resp = uc.getResponseCode();
- if (resp != 200)
- throw new RuntimeException("Failed: Response code from GET is not 200");
+ CookieHandler ch = CookieHandler.getDefault();
+ Map<String,List<String>> header = new HashMap<String,List<String>>();
+ List<String> values = new LinkedList<String>();
+ values.add("Test1Cookie=TEST1; path=/test/");
+ values.add("Test2Cookie=TEST2; path=/test/");
+ header.put("Set-Cookie", values);
- System.out.println("Response code from GET = 200 OK");
+ // preload the CookieHandler with a cookie for our URL
+ // so that it will be sent during the first request
+ ch.put(url.toURI(), header);
+ HttpURLConnection uc = (HttpURLConnection)url.openConnection();
+ int resp = uc.getResponseCode();
+ if (resp != 200) {
+ throw new RuntimeException("Failed: Response code from GET is not 200: "
+ + resp);
+ }
+ System.out.println("Response code from GET = 200 OK");
- } catch (IOException e) {
- e.printStackTrace();
- } catch (URISyntaxException e) {
- e.printStackTrace();
- } finally {
- httpServer.stop(1);
- executorService.shutdown();
- }
+ httpServer.stop(1);
+ executorService.shutdown();
}
/**
* Http Server
*/
public void startHttpServer() throws IOException {
- httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ InetSocketAddress address = new InetSocketAddress(loopback, 0);
+ httpServer = com.sun.net.httpserver.HttpServer.create(address, 0);
// create HttpServer context
HttpContext ctx = httpServer.createContext("/test/", new MyHandler());
--- a/test/jdk/sun/net/www/protocol/http/B6660405.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/B6660405.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,10 @@
* @test
* @bug 6660405
* @modules jdk.httpserver
- * @summary HttpURLConnection returns the wrong InputStream
+ * @library /test/lib
+ * @run main/othervm B6660405
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B6660405
+ * @summary HttpURLConnection returns the wrong InputStream B6660405
*/
import java.net.*;
@@ -34,6 +37,8 @@
import com.sun.net.httpserver.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
+import jdk.test.lib.net.URIBuilder;
+
public class B6660405
{
@@ -72,7 +77,8 @@
}
@Override
- public CacheResponse get(URI uri, String rqstMethod, Map<String, List<String>> rqstHeaders) throws IOException
+ public CacheResponse get(URI uri, String rqstMethod, Map<String, List<String>> rqstHeaders)
+ throws IOException
{
if (uri.getPath().equals("/redirect/index.html")) {
return new MyCacheResponse();
@@ -88,53 +94,61 @@
}
- public static void main(String[] args)
+ public static void main(String[] args) throws Exception
{
new B6660405();
}
- public B6660405()
- {
- try {
- startHttpServer();
- doClient();
- } catch (IOException ioe) {
- System.err.println(ioe);
- }
+ public B6660405() throws Exception {
+ startHttpServer();
+ doClient();
}
- void doClient() {
+ void doClient() throws Exception {
ResponseCache.setDefault(new MyResponseCache());
- try {
- InetSocketAddress address = httpServer.getAddress();
+ InetSocketAddress address = httpServer.getAddress();
+
+ // GET Request
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .host(address.getAddress())
+ .port(address.getPort())
+ .path("/test/index.html")
+ .toURL();
- // GET Request
- URL url = new URL("http://localhost:" + address.getPort() + "/test/index.html");
- HttpURLConnection uc = (HttpURLConnection)url.openConnection();
- int code = uc.getResponseCode();
- System.err.println("response code = " + code);
- int l = uc.getContentLength();
- System.err.println("content-length = " + l);
- InputStream in = uc.getInputStream();
- int i = 0;
- // Read till end of stream
- do {
- i = in.read();
- } while (i != -1);
- in.close();
- } catch (IOException e) {
- throw new RuntimeException("Got the wrong InputStream after checking headers");
- } finally {
- httpServer.stop(1);
- executorService.shutdown();
+ HttpURLConnection uc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
+ int code = uc.getResponseCode();
+ System.err.println("response code = " + code);
+ int l = uc.getContentLength();
+ System.err.println("content-length = " + l);
+ if (l != 1024) {
+ throw new AssertionError("Bad content length: " + l);
}
+
+ InputStream in = uc.getInputStream();
+ int i = 0;
+ // Read till end of stream
+ do {
+ l--;
+ i = in.read();
+ } while (i != -1);
+ in.close();
+ if (l != -1) {
+ throw new AssertionError("Only " + (1024 - (l + 1))
+ + " bytes read from stream.");
+ }
+
+ httpServer.stop(1);
+ executorService.shutdown();
}
/**
* Http Server
*/
public void startHttpServer() throws IOException {
- httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ InetSocketAddress address = new InetSocketAddress(loopback,0);
+ httpServer = com.sun.net.httpserver.HttpServer.create(address, 0);
// create HttpServer context
HttpContext ctx = httpServer.createContext("/test/", new MyHandler());
--- a/test/jdk/sun/net/www/protocol/http/B6890349.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/B6890349.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,9 @@
/**
* @test
* @bug 6890349
+ * @library /test/lib
* @run main/othervm B6890349
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B6890349
* @summary Light weight HTTP server
*/
@@ -34,7 +36,11 @@
public static final void main(String[] args) throws Exception {
try {
- ServerSocket server = new ServerSocket (0);
+ ServerSocket server = new ServerSocket();
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ InetSocketAddress address = new InetSocketAddress(loopback, 0);
+ server.bind(address);
+
int port = server.getLocalPort();
System.out.println ("listening on " + port);
B6890349 t = new B6890349 (server);
@@ -44,11 +50,11 @@
port,
"/foo\nbar");
System.out.println("URL: " + u);
- HttpURLConnection urlc = (HttpURLConnection)u.openConnection ();
+ HttpURLConnection urlc = (HttpURLConnection)u.openConnection(Proxy.NO_PROXY);
InputStream is = urlc.getInputStream();
throw new RuntimeException ("Test failed");
} catch (IOException e) {
- System.out.println ("OK");
+ System.out.println ("Caught expected exception: " + e);
}
}
--- a/test/jdk/sun/net/www/protocol/http/Modified.java Wed Jun 26 14:28:47 2019 +0530
+++ b/test/jdk/sun/net/www/protocol/http/Modified.java Fri Jun 28 14:36:42 2019 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,12 +24,16 @@
/*
* @test
* @bug 4092605
+ * @library /test/lib
+ * @run main/othervm Modified
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true Modified
* @summary Test HttpURLConnection setIfModifiedSince
*
*/
import java.net.*;
import java.io.*;
+import jdk.test.lib.net.URIBuilder;
public class Modified implements Runnable {
@@ -78,13 +82,22 @@
Modified() throws Exception {
- ss = new ServerSocket(0);
+ InetAddress loopback = InetAddress.getLoopbackAddress();
+ InetSocketAddress address = new InetSocketAddress(loopback, 0);
+ ss = new ServerSocket();
+ ss.bind(address);
+ int port = ss.getLocalPort();
+
Thread thr = new Thread(this);
thr.start();
- URL testURL = new URL("http://localhost:" + ss.getLocalPort() +
- "/index.html");
- URLConnection URLConn = testURL.openConnection();
+ URL testURL = URIBuilder.newBuilder()
+ .scheme("http")
+ .host(loopback)
+ .port(port)
+ .path("/index.html")
+ .toURL();
+ URLConnection URLConn = testURL.openConnection(Proxy.NO_PROXY);
HttpURLConnection httpConn;
if (URLConn instanceof HttpURLConnection) {