--- a/make/CompileJavaModules.gmk Mon Apr 23 12:53:43 2018 +0200
+++ b/make/CompileJavaModules.gmk Thu Apr 26 17:59:02 2018 +0200
@@ -439,7 +439,7 @@
#
jdk.internal.vm.compiler_EXCLUDES += \
- org.graalvm.collections.test \
+ jdk.internal.vm.compiler.collections.test \
org.graalvm.compiler.core.match.processor \
org.graalvm.compiler.nodeinfo.processor \
org.graalvm.compiler.options.processor \
--- a/make/CompileToolsHotspot.gmk Mon Apr 23 12:53:43 2018 +0200
+++ b/make/CompileToolsHotspot.gmk Thu Apr 26 17:59:02 2018 +0200
@@ -47,8 +47,8 @@
$(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := \
- $(SRC_DIR)/org.graalvm.word/src \
- $(SRC_DIR)/org.graalvm.collections/src \
+ $(SRC_DIR)/jdk.internal.vm.compiler.word/src \
+ $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \
$(SRC_DIR)/org.graalvm.compiler.core/src \
$(SRC_DIR)/org.graalvm.compiler.core.common/src \
$(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \
@@ -102,7 +102,7 @@
$(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_OPTIONS_PROCESSOR, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := \
- $(SRC_DIR)/org.graalvm.collections/src \
+ $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \
$(SRC_DIR)/org.graalvm.compiler.options/src \
$(SRC_DIR)/org.graalvm.compiler.options.processor/src \
$(SRC_DIR)/org.graalvm.util/src \
@@ -118,8 +118,8 @@
$(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := \
- $(SRC_DIR)/org.graalvm.word/src \
- $(SRC_DIR)/org.graalvm.collections/src \
+ $(SRC_DIR)/jdk.internal.vm.compiler.word/src \
+ $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \
$(SRC_DIR)/org.graalvm.compiler.bytecode/src \
$(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \
$(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
--- a/make/Images.gmk Mon Apr 23 12:53:43 2018 +0200
+++ b/make/Images.gmk Thu Apr 26 17:59:02 2018 +0200
@@ -117,7 +117,7 @@
JLINK_TOOL := $(JLINK) -J-Djlink.debug=true \
--module-path $(IMAGES_OUTPUTDIR)/jmods \
- --endian $(OPENJDK_BUILD_CPU_ENDIAN) \
+ --endian $(OPENJDK_TARGET_CPU_ENDIAN) \
--release-info $(BASE_RELEASE_FILE) \
--order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \
--dedup-legal-notices=error-if-not-same-content \
--- a/make/launcher/Launcher-jdk.pack.gmk Mon Apr 23 12:53:43 2018 +0200
+++ b/make/launcher/Launcher-jdk.pack.gmk Thu Apr 26 17:59:02 2018 +0200
@@ -88,7 +88,6 @@
CFLAGS_solaris := -KPIC, \
CFLAGS_macosx := -fPIC, \
DISABLED_WARNINGS_gcc := unused-result implicit-fallthrough, \
- DISABLED_WARNINGS_microsoft := 4005, \
LDFLAGS := $(UNPACKEXE_ZIPOBJS) \
$(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/make/lib/Lib-jdk.pack.gmk Mon Apr 23 12:53:43 2018 +0200
+++ b/make/lib/Lib-jdk.pack.gmk Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,6 @@
$(LIBJAVA_HEADER_FLAGS), \
CFLAGS_release := -DPRODUCT, \
DISABLED_WARNINGS_gcc := implicit-fallthrough, \
- DISABLED_WARNINGS_microsoft := 4005, \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_windows := -map:$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpack.map -debug, \
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
+#include "runtime/jniHandles.hpp"
#define __ masm->
@@ -64,3 +65,10 @@
default: Unimplemented();
}
}
+
+void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath) {
+ // If mask changes we need to ensure that the inverse is still encodable as an immediate
+ STATIC_ASSERT(JNIHandles::weak_tag_mask == 1);
+ __ andr(robj, robj, ~JNIHandles::weak_tag_mask);
+ __ ldr(robj, Address(robj, 0)); // *obj
+}
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -40,6 +40,8 @@
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2);
+ virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath);
+
virtual void barrier_stubs_init() {}
};
--- a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -25,6 +25,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "memory/resourceArea.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
@@ -82,11 +84,9 @@
// robj ^ rcounter ^ rcounter == robj
// robj is address dependent on rcounter.
- // If mask changes we need to ensure that the inverse is still encodable as an immediate
- STATIC_ASSERT(JNIHandles::weak_tag_mask == 1);
- __ andr(robj, robj, ~JNIHandles::weak_tag_mask);
+ BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->try_resolve_jobject_in_native(masm, robj, rscratch1, slow);
- __ ldr(robj, Address(robj, 0)); // *obj
__ lsr(roffset, c_rarg2, 2); // offset
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
@@ -177,4 +177,3 @@
address JNI_FastGetField::generate_fast_get_double_field() {
return generate_fast_get_int_field0(T_DOUBLE);
}
-
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -368,7 +368,7 @@
CodeBuffer cb(code_pos, instruction_size);
MacroAssembler a(&cb);
- a.mov(rscratch1, entry);
+ a.movptr(rscratch1, (uintptr_t)entry);
a.br(rscratch1);
ICache::invalidate_range(code_pos, instruction_size);
--- a/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interp_masm.hpp"
+#include "runtime/jniHandles.hpp"
#define __ masm->
@@ -98,3 +99,8 @@
default: Unimplemented();
}
}
+
+void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath) {
+ __ andn (robj, JNIHandles::weak_tag_mask, robj);
+ __ ld_ptr(robj, 0, robj);
+}
--- a/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -44,6 +44,9 @@
virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address src, Register dst, Register tmp);
+ // Support for jniFastGetField to try resolving a jobject/jweak in native
+ virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath);
+
virtual void barrier_stubs_init() {}
};
--- a/src/hotspot/cpu/sparc/jniFastGetField_sparc.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/sparc/jniFastGetField_sparc.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "memory/resourceArea.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
@@ -68,17 +70,18 @@
__ andcc (G4, 1, G0);
__ br (Assembler::notZero, false, Assembler::pn, label1);
__ delayed()->srl (O2, 2, O4);
- __ andn (O1, JNIHandles::weak_tag_mask, O1);
- __ ld_ptr (O1, 0, O5);
+
+ BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->try_resolve_jobject_in_native(masm, O1, G3_scratch, label1);
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
speculative_load_pclist[count] = __ pc();
switch (type) {
- case T_BOOLEAN: __ ldub (O5, O4, G3); break;
- case T_BYTE: __ ldsb (O5, O4, G3); break;
- case T_CHAR: __ lduh (O5, O4, G3); break;
- case T_SHORT: __ ldsh (O5, O4, G3); break;
- case T_INT: __ ld (O5, O4, G3); break;
+ case T_BOOLEAN: __ ldub (O1, O4, G3); break;
+ case T_BYTE: __ ldsb (O1, O4, G3); break;
+ case T_CHAR: __ lduh (O1, O4, G3); break;
+ case T_SHORT: __ ldsh (O1, O4, G3); break;
+ case T_INT: __ ld (O1, O4, G3); break;
default: ShouldNotReachHere();
}
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interp_masm.hpp"
+#include "runtime/jniHandles.hpp"
#define __ masm->
@@ -108,3 +109,8 @@
default: Unimplemented();
}
}
+
+void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath) {
+ __ clear_jweak_tag(robj);
+ __ movptr(robj, Address(robj, 0));
+}
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -44,6 +44,9 @@
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2);
+ // Support for jniFastGetField to try resolving a jobject/jweak in native
+ virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath);
+
virtual void barrier_stubs_init() {}
};
--- a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
#include "memory/resourceArea.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
@@ -81,12 +83,12 @@
// robj is data dependent on rcounter.
}
- __ clear_jweak_tag(robj);
-
- __ movptr(robj, Address(robj, 0)); // *obj
__ mov (roffset, c_rarg2);
__ shrptr(roffset, 2); // offset
+ BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->try_resolve_jobject_in_native(masm, robj, rscratch1, slow);
+
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
speculative_load_pclist[count] = __ pc();
switch (type) {
--- a/src/hotspot/share/adlc/formssel.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/adlc/formssel.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1171,6 +1171,9 @@
else if (is_ideal_nop()) {
return "MachNopNode";
}
+ else if (is_ideal_jump()) {
+ return "MachJumpNode";
+ }
else if (is_mach_constant()) {
return "MachConstantNode";
}
--- a/src/hotspot/share/adlc/output_c.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/adlc/output_c.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -3936,6 +3936,9 @@
fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent);
fprintf(fp_cpp, "%s node->_fcnt = _leaf->as_If()->_fcnt;\n", indent);
}
+ if (inst->is_ideal_jump()) {
+ fprintf(fp_cpp, "%s node->_probs = _leaf->as_Jump()->_probs;\n", indent);
+ }
if( inst->is_ideal_fastlock() ) {
fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent);
fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent);
--- a/src/hotspot/share/aot/aotCompiledMethod.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -285,7 +285,7 @@
protected:
virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred);
- virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) { return false; }
+ virtual bool do_unloading_jvmci(bool unloading_occurred) { return false; }
};
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1324,7 +1324,7 @@
void GraphBuilder::table_switch() {
Bytecode_tableswitch sw(stream());
const int l = sw.length();
- if (CanonicalizeNodes && l == 1) {
+ if (CanonicalizeNodes && l == 1 && compilation()->env()->comp_level() != CompLevel_full_profile) {
// total of 2 successors => use If instead of switch
// Note: This code should go into the canonicalizer as soon as it can
// can handle canonicalized forms that contain more than one node.
@@ -1368,7 +1368,7 @@
void GraphBuilder::lookup_switch() {
Bytecode_lookupswitch sw(stream());
const int l = sw.number_of_pairs();
- if (CanonicalizeNodes && l == 1) {
+ if (CanonicalizeNodes && l == 1 && compilation()->env()->comp_level() != CompLevel_full_profile) {
// total of 2 successors => use If instead of switch
// Note: This code should go into the canonicalizer as soon as it can
// can handle canonicalized forms that contain more than one node.
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -2558,6 +2558,36 @@
int hi_key = x->hi_key();
int len = x->length();
LIR_Opr value = tag.result();
+
+ if (compilation()->env()->comp_level() == CompLevel_full_profile && UseSwitchProfiling) {
+ ciMethod* method = x->state()->scope()->method();
+ ciMethodData* md = method->method_data_or_null();
+ ciProfileData* data = md->bci_to_data(x->state()->bci());
+ assert(data->is_MultiBranchData(), "bad profile data?");
+ int default_count_offset = md->byte_offset_of_slot(data, MultiBranchData::default_count_offset());
+ LIR_Opr md_reg = new_register(T_METADATA);
+ __ metadata2reg(md->constant_encoding(), md_reg);
+ LIR_Opr data_offset_reg = new_pointer_register();
+ LIR_Opr tmp_reg = new_pointer_register();
+
+ __ move(LIR_OprFact::intptrConst(default_count_offset), data_offset_reg);
+ for (int i = 0; i < len; i++) {
+ int count_offset = md->byte_offset_of_slot(data, MultiBranchData::case_count_offset(i));
+ __ cmp(lir_cond_equal, value, i + lo_key);
+ __ move(data_offset_reg, tmp_reg);
+ __ cmove(lir_cond_equal,
+ LIR_OprFact::intptrConst(count_offset),
+ tmp_reg,
+ data_offset_reg, T_INT);
+ }
+
+ LIR_Opr data_reg = new_pointer_register();
+ LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type());
+ __ move(data_addr, data_reg);
+ __ add(data_reg, LIR_OprFact::intptrConst(1), data_reg);
+ __ move(data_reg, data_addr);
+ }
+
if (UseTableRanges) {
do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux());
} else {
@@ -2583,6 +2613,37 @@
move_to_phi(x->state());
LIR_Opr value = tag.result();
+ int len = x->length();
+
+ if (compilation()->env()->comp_level() == CompLevel_full_profile && UseSwitchProfiling) {
+ ciMethod* method = x->state()->scope()->method();
+ ciMethodData* md = method->method_data_or_null();
+ ciProfileData* data = md->bci_to_data(x->state()->bci());
+ assert(data->is_MultiBranchData(), "bad profile data?");
+ int default_count_offset = md->byte_offset_of_slot(data, MultiBranchData::default_count_offset());
+ LIR_Opr md_reg = new_register(T_METADATA);
+ __ metadata2reg(md->constant_encoding(), md_reg);
+ LIR_Opr data_offset_reg = new_pointer_register();
+ LIR_Opr tmp_reg = new_pointer_register();
+
+ __ move(LIR_OprFact::intptrConst(default_count_offset), data_offset_reg);
+ for (int i = 0; i < len; i++) {
+ int count_offset = md->byte_offset_of_slot(data, MultiBranchData::case_count_offset(i));
+ __ cmp(lir_cond_equal, value, x->key_at(i));
+ __ move(data_offset_reg, tmp_reg);
+ __ cmove(lir_cond_equal,
+ LIR_OprFact::intptrConst(count_offset),
+ tmp_reg,
+ data_offset_reg, T_INT);
+ }
+
+ LIR_Opr data_reg = new_pointer_register();
+ LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type());
+ __ move(data_addr, data_reg);
+ __ add(data_reg, LIR_OprFact::intptrConst(1), data_reg);
+ __ move(data_reg, data_addr);
+ }
+
if (UseTableRanges) {
do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux());
} else {
--- a/src/hotspot/share/code/codeHeapState.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/codeHeapState.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -2050,16 +2050,10 @@
}
-#define JDK8200450_REMEDY
-#define JDK8200450_TRACE
void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) {
if (!initialization_complete) {
return;
}
-#ifdef JDK8200450_TRACE
- out->print_cr("print_names() entered for heap @ " INTPTR_FORMAT, p2i(heap));
- out->flush();
-#endif
const char* heapName = get_heapName(heap);
get_HeapStatGlobals(out, heapName);
@@ -2105,41 +2099,18 @@
// Only check granule if it contains at least one blob.
unsigned int nBlobs = StatArray[ix].t1_count + StatArray[ix].t2_count + StatArray[ix].tx_count +
StatArray[ix].stub_count + StatArray[ix].dead_count;
-#ifdef JDK8200450_REMEDY
- if (nBlobs > 0 )
-#endif
- {
+ if (nBlobs > 0 ) {
for (unsigned int is = 0; is < granule_size; is+=(unsigned int)seg_size) {
// heap->find_start() is safe. Only working with _segmap. Returns NULL or void*. Returned CodeBlob may be uninitialized.
CodeBlob* this_blob = (CodeBlob *)(heap->find_start(low_bound+ix*granule_size+is));
-#ifndef JDK8200450_REMEDY
- bool blob_initialized = (this_blob != NULL)
-#else
-#ifndef JDK8200450_TRACE
bool blob_initialized = (this_blob != NULL) && (this_blob->header_size() >= 0) && (this_blob->relocation_size() >= 0) &&
((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) &&
- ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin()) &&
- is_readable_pointer((address)(this_blob->relocation_begin()) &&
+ ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin())) &&
+ is_readable_pointer((address)(this_blob->relocation_begin())) &&
is_readable_pointer(this_blob->content_begin());
-#else
- int hdr_size = 0;
- int reloc_size = 0;
- address reloc_begin = NULL;
- address cntnt_begin = NULL;
- if (this_blob != NULL) {
- hdr_size = this_blob->header_size();
- reloc_size = this_blob->relocation_size();
- reloc_begin = (address)(this_blob->relocation_begin());
- cntnt_begin = this_blob->content_begin();
- }
- bool blob_initialized = (this_blob != NULL) && (hdr_size >= 0) && (reloc_size >= 0) &&
- ((address)this_blob + hdr_size == reloc_begin) &&
- ((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin) &&
- is_readable_pointer(reloc_begin) &&
- is_readable_pointer(cntnt_begin);
-#endif
-#endif
- if (blob_initialized && (this_blob != last_blob)) {
+ // blob could have been flushed, freed, and merged.
+ // this_blob < last_blob is an indicator for that.
+ if (blob_initialized && (this_blob > last_blob)) {
last_blob = this_blob;
//---< get type and name >---
@@ -2147,15 +2118,13 @@
if (segment_granules) {
cbType = (blobType)StatArray[ix].type;
} else {
- cbType = get_cbType(this_blob); // Is this here safe?
+ cbType = get_cbType(this_blob);
}
- // this_blob->name() could return NULL if no name is given to CTOR. Inlined, maybe invisible on stack
+ // this_blob->name() could return NULL if no name was given to CTOR. Inlined, maybe invisible on stack
const char* blob_name = this_blob->name();
-#ifdef JDK8200450_REMEDY
- if (blob_name == NULL) {
+ if ((blob_name == NULL) || !is_readable_pointer(blob_name)) {
blob_name = "<unavailable>";
}
-#endif
//---< print table header for new print range >---
if (!name_in_addr_range) {
@@ -2174,24 +2143,16 @@
ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
ast->fill_to(33);
-#ifdef JDK8200450_TRACE
- STRINGSTREAM_FLUSH_LOCKED("") // Remove before push!!!
-#endif
-
// this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
nmethod* nm = this_blob->as_nmethod_or_null();
Method* method = (nm == NULL) ? NULL : nm->method(); // may be uninitialized, i.e. != NULL, but invalid
-#ifdef JDK8200450_REMEDY
- if ((nm != NULL) && (method != NULL) && is_readable_pointer(method) && is_readable_pointer(method->constants())) {
-#else
- if ((nm != NULL) && (method != NULL)) {
-#endif
+ if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) &&
+ is_readable_pointer(method) && is_readable_pointer(method->constants())) {
ResourceMark rm;
//---< collect all data to locals as quickly as possible >---
unsigned int total_size = nm->total_size();
int hotness = nm->hotness_counter();
- bool nm_zombie = nm->is_zombie();
- bool get_name = nm->is_in_use() || nm->is_not_entrant();
+ bool get_name = (cbType == nMethod_inuse) || (cbType == nMethod_notused);
//---< nMethod size in hex >---
ast->print(PTR32_FORMAT, total_size);
ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
@@ -2205,16 +2166,11 @@
ast->fill_to(62+6);
ast->print("%s", blobTypeName[cbType]);
ast->fill_to(82+6);
- if (nm_zombie) {
+ if (cbType == nMethod_dead) {
ast->print("%14s", " zombie method");
}
-#ifdef JDK8200450_TRACE
- STRINGSTREAM_FLUSH_LOCKED("") // Remove before push!!!
-#endif
-
if (get_name) {
-#ifdef JDK8200450_REMEDY
Symbol* methName = method->name();
const char* methNameS = (methName == NULL) ? NULL : methName->as_C_string();
methNameS = (methNameS == NULL) ? "<method name unavailable>" : methNameS;
@@ -2223,10 +2179,6 @@
methSigS = (methSigS == NULL) ? "<method signature unavailable>" : methSigS;
ast->print("%s", methNameS);
ast->print("%s", methSigS);
-#else
- blob_name = method->name_and_sig_as_C_string();
- ast->print("%s", blob_name);
-#endif
} else {
ast->print("%s", blob_name);
}
@@ -2237,45 +2189,9 @@
ast->print("%s", blob_name);
}
STRINGSTREAM_FLUSH_LOCKED("\n")
-#ifdef JDK8200450_TRACE
- if ((nm != NULL) && (method != NULL) && !(is_readable_pointer(method) && is_readable_pointer(method->constants()))) {
- ast->print("Potential CodeHeap State Analytics issue found.\n");
- if (is_readable_pointer(method)) {
- ast->print(" Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method->constants())) check.\n", p2i(method->constants()));
- } else {
- ast->print(" Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method)) check.\n", p2i(method));
- }
- STRINGSTREAM_FLUSH_LOCKED("\n")
- }
-#endif
} else if (!blob_initialized && (this_blob != last_blob) && (this_blob != NULL)) {
last_blob = this_blob;
-#ifdef JDK8200450_TRACE
- ast->print("Potential CodeHeap State Analytics issue found.\n");
- if (nBlobs == 0) {
- ast->print(" Issue would have been detected by (nBlobs > 0) check.\n");
- } else {
- if (!((address)this_blob + hdr_size == reloc_begin)) {
- ast->print(" Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) == relocation_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, p2i(reloc_begin));
- }
- if (!((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin)) {
- ast->print(" Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) + relocation(%d) == content_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, reloc_size, p2i(cntnt_begin));
- }
- if (hdr_size != this_blob->header_size()) {
- ast->print(" header_size meanwhile changed from %d to %d\n", hdr_size, this_blob->header_size());
- }
- if (reloc_size != this_blob->relocation_size()) {
- ast->print(" relocation_size meanwhile changed from %d to %d\n", reloc_size, this_blob->relocation_size());
- }
- if (reloc_begin != (address)(this_blob->relocation_begin())) {
- ast->print(" relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(reloc_begin), p2i(this_blob->relocation_begin()));
- }
- if (cntnt_begin != this_blob->content_begin()) {
- ast->print(" relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(cntnt_begin), p2i(this_blob->content_begin()));
- }
- }
STRINGSTREAM_FLUSH_LOCKED("\n")
-#endif
}
}
} // nBlobs > 0
@@ -2430,7 +2346,7 @@
}
CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) {
- if (cb != NULL ) {
+ if ((cb != NULL) && is_readable_pointer(cb)) {
if (cb->is_runtime_stub()) return runtimeStub;
if (cb->is_deoptimization_stub()) return deoptimizationStub;
if (cb->is_uncommon_trap_stub()) return uncommonTrapStub;
@@ -2440,13 +2356,13 @@
if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob;
if (cb->is_buffer_blob()) return bufferBlob;
- if (cb->is_nmethod() ) {
- if (((nmethod*)cb)->is_in_use()) return nMethod_inuse;
- if (((nmethod*)cb)->is_alive() && !(((nmethod*)cb)->is_not_entrant())) return nMethod_notused;
- if (((nmethod*)cb)->is_alive()) return nMethod_alive;
- if (((nmethod*)cb)->is_unloaded()) return nMethod_unloaded;
- if (((nmethod*)cb)->is_zombie()) return nMethod_dead;
- tty->print_cr("unhandled nmethod state");
+ nmethod* nm = cb->as_nmethod_or_null();
+ if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb.
+ if (nm->is_zombie()) return nMethod_dead;
+ if (nm->is_unloaded()) return nMethod_unloaded;
+ if (nm->is_alive() && !(nm->is_not_entrant())) return nMethod_notused;
+ if (nm->is_alive()) return nMethod_alive;
+ if (nm->is_in_use()) return nMethod_inuse;
return nMethod_dead;
}
}
--- a/src/hotspot/share/code/compiledMethod.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/compiledMethod.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -525,7 +525,7 @@
}
#if INCLUDE_JVMCI
- if (do_unloading_jvmci(is_alive, unloading_occurred)) {
+ if (do_unloading_jvmci(unloading_occurred)) {
return;
}
#endif
@@ -535,7 +535,7 @@
}
template <class CompiledICorStaticCall>
-static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, BoolObjectClosure *is_alive, CompiledMethod* from) {
+static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, CompiledMethod* from) {
// Ok, to lookup references to zombies here
CodeBlob *cb = CodeCache::find_blob_unsafe(addr);
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
@@ -555,12 +555,12 @@
return false;
}
-static bool clean_if_nmethod_is_unloaded(CompiledIC *ic, BoolObjectClosure *is_alive, CompiledMethod* from) {
- return clean_if_nmethod_is_unloaded(ic, ic->ic_destination(), is_alive, from);
+static bool clean_if_nmethod_is_unloaded(CompiledIC *ic, CompiledMethod* from) {
+ return clean_if_nmethod_is_unloaded(ic, ic->ic_destination(), from);
}
-static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, BoolObjectClosure *is_alive, CompiledMethod* from) {
- return clean_if_nmethod_is_unloaded(csc, csc->destination(), is_alive, from);
+static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, CompiledMethod* from) {
+ return clean_if_nmethod_is_unloaded(csc, csc->destination(), from);
}
bool CompiledMethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred) {
@@ -608,15 +608,15 @@
clean_ic_if_metadata_is_dead(CompiledIC_at(&iter));
}
- postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+ postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
break;
case relocInfo::opt_virtual_call_type:
- postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+ postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
break;
case relocInfo::static_call_type:
- postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
+ postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this);
break;
case relocInfo::oop_type:
@@ -636,7 +636,7 @@
}
#if INCLUDE_JVMCI
- if (do_unloading_jvmci(is_alive, unloading_occurred)) {
+ if (do_unloading_jvmci(unloading_occurred)) {
return postponed;
}
#endif
@@ -647,7 +647,7 @@
return postponed;
}
-void CompiledMethod::do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred) {
+void CompiledMethod::do_unloading_parallel_postponed() {
ResourceMark rm;
// Make sure the oop's ready to receive visitors
@@ -671,15 +671,15 @@
switch (iter.type()) {
case relocInfo::virtual_call_type:
- clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+ clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
break;
case relocInfo::opt_virtual_call_type:
- clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+ clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
break;
case relocInfo::static_call_type:
- clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
+ clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this);
break;
default:
--- a/src/hotspot/share/code/compiledMethod.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/compiledMethod.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -372,7 +372,7 @@
virtual void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
// The parallel versions are used by G1.
virtual bool do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred);
- virtual void do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred);
+ virtual void do_unloading_parallel_postponed();
static unsigned char global_unloading_clock() { return _global_unloading_clock; }
static void increase_unloading_clock();
@@ -383,7 +383,7 @@
protected:
virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred) = 0;
#if INCLUDE_JVMCI
- virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) = 0;
+ virtual bool do_unloading_jvmci(bool unloading_occurred) = 0;
#endif
private:
--- a/src/hotspot/share/code/nmethod.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/nmethod.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1028,17 +1028,16 @@
mdo->inc_decompile_count();
}
-void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
+void nmethod::make_unloaded(oop cause) {
post_compiled_method_unload();
- // Since this nmethod is being unloaded, make sure that dependencies
- // recorded in instanceKlasses get flushed and pass non-NULL closure to
- // indicate that this work is being done during a GC.
+ // This nmethod is being unloaded, make sure that dependencies
+ // recorded in instanceKlasses get flushed.
+ // Since this work is being done during a GC, defer deleting dependencies from the
+ // InstanceKlass.
assert(Universe::heap()->is_gc_active(), "should only be called during gc");
- assert(is_alive != NULL, "Should be non-NULL");
- // A non-NULL is_alive closure indicates that this is being called during GC.
- flush_dependencies(is_alive);
+ flush_dependencies(/*delete_immediately*/false);
// Break cycle between nmethod & method
LogTarget(Trace, class, unload) lt;
@@ -1261,7 +1260,7 @@
if (nmethod_needs_unregister) {
Universe::heap()->unregister_nmethod(this);
}
- flush_dependencies(NULL);
+ flush_dependencies(/*delete_immediately*/true);
}
// zombie only - if a JVMTI agent has enabled the CompiledMethodUnload
@@ -1344,13 +1343,13 @@
// of dependencies must happen during phase 1 since after GC any
// dependencies in the unloaded nmethod won't be updated, so
// traversing the dependency information in unsafe. In that case this
-// function is called with a non-NULL argument and this function only
+// function is called with a boolean argument and this function only
// notifies instanceKlasses that are reachable
-void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
+void nmethod::flush_dependencies(bool delete_immediately) {
assert_locked_or_safepoint(CodeCache_lock);
- assert(Universe::heap()->is_gc_active() == (is_alive != NULL),
- "is_alive is non-NULL if and only if we are called during GC");
+ assert(Universe::heap()->is_gc_active() != delete_immediately,
+ "delete_immediately is false if and only if we are called during GC");
if (!has_flushed_dependencies()) {
set_has_flushed_dependencies();
for (Dependencies::DepStream deps(this); deps.next(); ) {
@@ -1363,13 +1362,12 @@
if (klass == NULL) {
continue; // ignore things like evol_method
}
- // During GC the is_alive closure is non-NULL, and is used to
- // determine liveness of dependees that need to be updated.
- if (is_alive == NULL || klass->is_loader_alive()) {
+ // During GC delete_immediately is false, and liveness
+ // of dependee determines class that needs to be updated.
+ if (delete_immediately || klass->is_loader_alive()) {
// The GC defers deletion of this entry, since there might be multiple threads
// iterating over the _dependencies graph. Other call paths are single-threaded
// and may delete it immediately.
- bool delete_immediately = is_alive == NULL;
InstanceKlass::cast(klass)->remove_dependent_nmethod(this, delete_immediately);
}
}
@@ -1390,7 +1388,7 @@
// simply because one of its constant oops has gone dead.
// No actual classes need to be unloaded in order for this to occur.
assert(unloading_occurred || ScavengeRootsInCode, "Inconsistency in unloading");
- make_unloaded(is_alive, obj);
+ make_unloaded(obj);
return true;
}
@@ -1516,12 +1514,12 @@
}
#if INCLUDE_JVMCI
-bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) {
+bool nmethod::do_unloading_jvmci(bool unloading_occurred) {
if (_jvmci_installed_code != NULL) {
if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
if (_jvmci_installed_code_triggers_unloading) {
// jweak reference processing has already cleared the referent
- make_unloaded(is_alive, NULL);
+ make_unloaded(NULL);
return true;
} else {
clear_jvmci_installed_code();
--- a/src/hotspot/share/code/nmethod.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/nmethod.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -349,10 +349,10 @@
return _state;
}
- void make_unloaded(BoolObjectClosure* is_alive, oop cause);
+ void make_unloaded(oop cause);
bool has_dependencies() { return dependencies_size() != 0; }
- void flush_dependencies(BoolObjectClosure* is_alive);
+ void flush_dependencies(bool delete_immediately);
bool has_flushed_dependencies() { return _has_flushed_dependencies; }
void set_has_flushed_dependencies() {
assert(!has_flushed_dependencies(), "should only happen once");
@@ -488,7 +488,7 @@
#if INCLUDE_JVMCI
// See comment for _jvmci_installed_code_triggers_unloading field.
// Returns whether this nmethod was unloaded.
- virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred);
+ virtual bool do_unloading_jvmci(bool unloading_occurred);
#endif
private:
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -3353,7 +3353,7 @@
}
void clean_nmethod_postponed(CompiledMethod* nm) {
- nm->do_unloading_parallel_postponed(_is_alive, _unloading_occurred);
+ nm->do_unloading_parallel_postponed();
}
static const int MaxClaimNmethods = 16;
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1695,14 +1695,6 @@
assert(!rp->discovery_enabled(), "Post condition");
}
- assert(has_overflown() || _global_mark_stack.is_empty(),
- "Mark stack should be empty (unless it has overflown)");
-
- {
- GCTraceTime(Debug, gc, phases) debug("Weak Processing", _gc_timer_cm);
- WeakProcessor::weak_oops_do(&g1_is_alive, &do_nothing_cl);
- }
-
if (has_overflown()) {
// We can not trust g1_is_alive if the marking stack overflowed
return;
@@ -1710,6 +1702,11 @@
assert(_global_mark_stack.is_empty(), "Marking should have completed");
+ {
+ GCTraceTime(Debug, gc, phases) debug("Weak Processing", _gc_timer_cm);
+ WeakProcessor::weak_oops_do(&g1_is_alive, &do_nothing_cl);
+ }
+
// Unload Klasses, String, Symbols, Code Cache, etc.
if (ClassUnloadingWithConcurrentMark) {
GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm);
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -172,6 +172,22 @@
return false;
}
+bool CollectedHeap::is_oop(oop object) const {
+ if (!check_obj_alignment(object)) {
+ return false;
+ }
+
+ if (!is_in_reserved(object)) {
+ return false;
+ }
+
+ if (is_in_reserved(object->klass_or_null())) {
+ return false;
+ }
+
+ return true;
+}
+
// Memory state functions.
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -592,6 +592,8 @@
virtual oop pin_object(JavaThread* thread, oop obj);
virtual void unpin_object(JavaThread* thread, oop obj);
+ virtual bool is_oop(oop object) const;
+
// Non product verification and debugging.
#ifndef PRODUCT
// Support for PromotionFailureALot. Return true if it's time to cause a
--- a/src/hotspot/share/memory/filemap.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/memory/filemap.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -75,6 +75,7 @@
class FileMapInfo : public CHeapObj<mtInternal> {
private:
friend class ManifestStream;
+ friend class VMStructs;
enum {
_invalid_version = -1,
_current_version = 3
--- a/src/hotspot/share/memory/metaspace.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/memory/metaspace.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -3378,6 +3378,7 @@
}
MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
+ assert_lock_strong(_lock);
assert(vs_list()->current_virtual_space() != NULL,
"Should have been set");
assert(current_chunk() == NULL ||
@@ -3406,7 +3407,16 @@
// and do an allocation from it.
if (next != NULL) {
// Add to this manager's list of chunks in use.
- add_chunk(next, false);
+ // If the new chunk is humongous, it was created to serve a single large allocation. In that
+ // case it usually makes no sense to make it the current chunk, since the next allocation would
+ // need to allocate a new chunk anyway, while we would now prematurely retire a perfectly
+ // good chunk which could be used for more normal allocations.
+ bool make_current = true;
+ if (next->get_chunk_type() == HumongousIndex &&
+ current_chunk() != NULL) {
+ make_current = false;
+ }
+ add_chunk(next, make_current);
mem = next->allocate(word_size);
}
@@ -3553,6 +3563,7 @@
// Adds a chunk to the list of chunks in use.
void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
+ assert_lock_strong(_lock);
assert(new_chunk != NULL, "Should not be NULL");
assert(new_chunk->next() == NULL, "Should not be on a list");
@@ -3562,28 +3573,16 @@
// chunk for that list.
ChunkIndex index = chunk_manager()->list_index(new_chunk->word_size());
- if (index != HumongousIndex) {
+ if (make_current) {
+ // If we are to make the chunk current, retire the old current chunk and replace
+ // it with the new chunk.
retire_current_chunk();
set_current_chunk(new_chunk);
- new_chunk->set_next(chunks_in_use(index));
- set_chunks_in_use(index, new_chunk);
- } else {
- // For null class loader data and DumpSharedSpaces, the first chunk isn't
- // small, so small will be null. Link this first chunk as the current
- // chunk.
- if (make_current) {
- // Set as the current chunk but otherwise treat as a humongous chunk.
- set_current_chunk(new_chunk);
- }
- // Link at head. The _current_chunk only points to a humongous chunk for
- // the null class loader metaspace (class and data virtual space managers)
- // any humongous chunks so will not point to the tail
- // of the humongous chunks list.
- new_chunk->set_next(chunks_in_use(HumongousIndex));
- set_chunks_in_use(HumongousIndex, new_chunk);
-
- assert(new_chunk->word_size() > medium_chunk_size(), "List inconsistency");
- }
+ }
+
+ // Add the new chunk at the head of its respective chunk list.
+ new_chunk->set_next(chunks_in_use(index));
+ set_chunks_in_use(index, new_chunk);
// Add to the running sum of capacity
inc_size_metrics(new_chunk->word_size());
@@ -4800,7 +4799,7 @@
void ClassLoaderMetaspace::initialize_first_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) {
Metachunk* chunk = get_initialization_chunk(type, mdtype);
if (chunk != NULL) {
- // Add to this manager's list of chunks in use and current_chunk().
+ // Add to this manager's list of chunks in use and make it the current_chunk().
get_space_manager(mdtype)->add_chunk(chunk, true);
}
}
--- a/src/hotspot/share/oops/oop.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/oops/oop.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -122,10 +122,9 @@
// used only for asserts and guarantees
bool oopDesc::is_oop(oop obj, bool ignore_mark_word) {
- if (!check_obj_alignment(obj)) return false;
- if (!Universe::heap()->is_in_reserved(obj)) return false;
- // obj is aligned and accessible in heap
- if (Universe::heap()->is_in_reserved(obj->klass_or_null())) return false;
+ if (!Universe::heap()->is_oop(obj)) {
+ return false;
+ }
// Header verification: the mark is typically non-NULL. If we're
// at a safepoint, it must not be null.
--- a/src/hotspot/share/opto/cfgnode.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/cfgnode.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -298,6 +298,7 @@
void reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn);
ProjNode* uncommon_trap_proj(CallStaticJavaNode*& call) const;
bool fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn);
+ static bool is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc);
protected:
ProjNode* range_check_trap_proj(int& flip, Node*& l, Node*& r);
@@ -484,8 +485,13 @@
// Indirect branch. Uses PCTable above to implement a switch statement.
// It emits as a table load and local branch.
class JumpNode : public PCTableNode {
+ virtual uint size_of() const { return sizeof(*this); }
public:
- JumpNode( Node* control, Node* switch_val, uint size) : PCTableNode(control, switch_val, size) {
+ float* _probs; // probability of each projection
+ float _fcnt; // total number of times this Jump was executed
+ JumpNode( Node* control, Node* switch_val, uint size, float* probs, float cnt)
+ : PCTableNode(control, switch_val, size),
+ _probs(probs), _fcnt(cnt) {
init_class_id(Class_Jump);
}
virtual int Opcode() const;
--- a/src/hotspot/share/opto/gcm.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/gcm.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1867,8 +1867,7 @@
}
case Op_Jump:
- // Divide the frequency between all successors evenly
- return 1.0f/_num_succs;
+ return n->as_MachJump()->_probs[get_node(i + eidx + 1)->as_JumpProj()->_con];
case Op_Catch: {
const CatchProjNode *ci = get_node(i + eidx + 1)->as_CatchProj();
--- a/src/hotspot/share/opto/ifnode.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/ifnode.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -775,6 +775,38 @@
return success != NULL && fail != NULL;
}
+bool IfNode::is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc) {
+ // Different methods and methods containing jsrs are not supported.
+ ciMethod* method = unc->jvms()->method();
+ ciMethod* dom_method = dom_unc->jvms()->method();
+ if (method != dom_method || method->has_jsrs()) {
+ return false;
+ }
+ // Check that both traps are in the same activation of the method (instead
+ // of two activations being inlined through different call sites) by verifying
+ // that the call stacks are equal for both JVMStates.
+ JVMState* dom_caller = dom_unc->jvms()->caller();
+ JVMState* caller = unc->jvms()->caller();
+ if ((dom_caller == NULL) != (caller == NULL)) {
+ // The current method must either be inlined into both dom_caller and
+ // caller or must not be inlined at all (top method). Bail out otherwise.
+ return false;
+ } else if (dom_caller != NULL && !dom_caller->same_calls_as(caller)) {
+ return false;
+ }
+ // Check that the bci of the dominating uncommon trap dominates the bci
+ // of the dominated uncommon trap. Otherwise we may not re-execute
+ // the dominated check after deoptimization from the merged uncommon trap.
+ ciTypeFlow* flow = dom_method->get_flow_analysis();
+ int bci = unc->jvms()->bci();
+ int dom_bci = dom_unc->jvms()->bci();
+ if (!flow->is_dominated_by(bci, dom_bci)) {
+ return false;
+ }
+
+ return true;
+}
+
// Return projection that leads to an uncommon trap if any
ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call) const {
for (int i = 0; i < 2; i++) {
@@ -811,31 +843,7 @@
return false;
}
- // Different methods and methods containing jsrs are not supported.
- ciMethod* method = unc->jvms()->method();
- ciMethod* dom_method = dom_unc->jvms()->method();
- if (method != dom_method || method->has_jsrs()) {
- return false;
- }
- // Check that both traps are in the same activation of the method (instead
- // of two activations being inlined through different call sites) by verifying
- // that the call stacks are equal for both JVMStates.
- JVMState* dom_caller = dom_unc->jvms()->caller();
- JVMState* caller = unc->jvms()->caller();
- if ((dom_caller == NULL) != (caller == NULL)) {
- // The current method must either be inlined into both dom_caller and
- // caller or must not be inlined at all (top method). Bail out otherwise.
- return false;
- } else if (dom_caller != NULL && !dom_caller->same_calls_as(caller)) {
- return false;
- }
- // Check that the bci of the dominating uncommon trap dominates the bci
- // of the dominated uncommon trap. Otherwise we may not re-execute
- // the dominated check after deoptimization from the merged uncommon trap.
- ciTypeFlow* flow = dom_method->get_flow_analysis();
- int bci = unc->jvms()->bci();
- int dom_bci = dom_unc->jvms()->bci();
- if (!flow->is_dominated_by(bci, dom_bci)) {
+ if (!is_dominator_unc(dom_unc, unc)) {
return false;
}
@@ -843,6 +851,8 @@
// will be changed and the state of the dominating If will be
// used. Checked that we didn't apply this transformation in a
// previous compilation and it didn't cause too many traps
+ ciMethod* dom_method = dom_unc->jvms()->method();
+ int dom_bci = dom_unc->jvms()->bci();
if (!igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_unstable_fused_if) &&
!igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_range_check)) {
success = unc_proj;
@@ -1220,6 +1230,10 @@
return false;
}
+ if (!is_dominator_unc(dom_unc, unc)) {
+ return false;
+ }
+
return true;
}
}
--- a/src/hotspot/share/opto/machnode.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/machnode.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -750,6 +750,16 @@
#endif
};
+//------------------------------MachJumpNode-----------------------------------
+// Machine-specific versions of JumpNodes
+class MachJumpNode : public MachConstantNode {
+public:
+ float* _probs;
+ MachJumpNode() : MachConstantNode() {
+ init_class_id(Class_MachJump);
+ }
+};
+
//------------------------------MachGotoNode-----------------------------------
// Machine-specific versions of GotoNodes
class MachGotoNode : public MachBranchNode {
--- a/src/hotspot/share/opto/node.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/node.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -94,6 +94,7 @@
class MachConstantNode;
class MachGotoNode;
class MachIfNode;
+class MachJumpNode;
class MachNode;
class MachNullCheckNode;
class MachProjNode;
@@ -651,6 +652,7 @@
DEFINE_CLASS_ID(MachTemp, Mach, 3)
DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
DEFINE_CLASS_ID(MachConstant, Mach, 5)
+ DEFINE_CLASS_ID(MachJump, MachConstant, 0)
DEFINE_CLASS_ID(MachMerge, Mach, 6)
DEFINE_CLASS_ID(Type, Node, 2)
@@ -831,6 +833,7 @@
DEFINE_CLASS_QUERY(MachConstant)
DEFINE_CLASS_QUERY(MachGoto)
DEFINE_CLASS_QUERY(MachIf)
+ DEFINE_CLASS_QUERY(MachJump)
DEFINE_CLASS_QUERY(MachNullCheck)
DEFINE_CLASS_QUERY(MachProj)
DEFINE_CLASS_QUERY(MachReturn)
--- a/src/hotspot/share/opto/parse.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/parse.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -552,17 +552,18 @@
void sharpen_type_after_if(BoolTest::mask btest,
Node* con, const Type* tcon,
Node* val, const Type* tval);
- IfNode* jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask);
+ IfNode* jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask, float prob, float cnt);
Node* jump_if_join(Node* iffalse, Node* iftrue);
- void jump_if_true_fork(IfNode *ifNode, int dest_bci_if_true, int prof_table_index);
- void jump_if_false_fork(IfNode *ifNode, int dest_bci_if_false, int prof_table_index);
- void jump_if_always_fork(int dest_bci_if_true, int prof_table_index);
+ void jump_if_true_fork(IfNode *ifNode, int dest_bci_if_true, int prof_table_index, bool unc);
+ void jump_if_false_fork(IfNode *ifNode, int dest_bci_if_false, int prof_table_index, bool unc);
+ void jump_if_always_fork(int dest_bci_if_true, int prof_table_index, bool unc);
friend class SwitchRange;
void do_tableswitch();
void do_lookupswitch();
void jump_switch_ranges(Node* a, SwitchRange* lo, SwitchRange* hi, int depth = 0);
bool create_jump_tables(Node* a, SwitchRange* lo, SwitchRange* hi);
+ void linear_search_switch_ranges(Node* key_val, SwitchRange*& lo, SwitchRange*& hi);
void decrement_age();
// helper functions for methodData style profiling
--- a/src/hotspot/share/opto/parse2.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/parse2.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -186,10 +186,10 @@
// returns IfNode
-IfNode* Parse::jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask) {
- Node *cmp = _gvn.transform( new CmpINode( a, b)); // two cases: shiftcount > 32 and shiftcount <= 32
- Node *tst = _gvn.transform( new BoolNode( cmp, mask));
- IfNode *iff = create_and_map_if( control(), tst, ((mask == BoolTest::eq) ? PROB_STATIC_INFREQUENT : PROB_FAIR), COUNT_UNKNOWN );
+IfNode* Parse::jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask, float prob, float cnt) {
+ Node *cmp = _gvn.transform(new CmpINode(a, b)); // two cases: shiftcount > 32 and shiftcount <= 32
+ Node *tst = _gvn.transform(new BoolNode(cmp, mask));
+ IfNode *iff = create_and_map_if(control(), tst, prob, cnt);
return iff;
}
@@ -205,15 +205,27 @@
return region;
}
+// sentinel value for the target bci to mark never taken branches
+// (according to profiling)
+static const int never_reached = INT_MAX;
//------------------------------helper for tableswitch-------------------------
-void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index) {
+void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index, bool unc) {
// True branch, use existing map info
{ PreserveJVMState pjvms(this);
Node *iftrue = _gvn.transform( new IfTrueNode (iff) );
set_control( iftrue );
- profile_switch_case(prof_table_index);
- merge_new_path(dest_bci_if_true);
+ if (unc) {
+ repush_if_args();
+ uncommon_trap(Deoptimization::Reason_unstable_if,
+ Deoptimization::Action_reinterpret,
+ NULL,
+ "taken always");
+ } else {
+ assert(dest_bci_if_true != never_reached, "inconsistent dest");
+ profile_switch_case(prof_table_index);
+ merge_new_path(dest_bci_if_true);
+ }
}
// False branch
@@ -221,13 +233,22 @@
set_control( iffalse );
}
-void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index) {
+void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index, bool unc) {
// True branch, use existing map info
{ PreserveJVMState pjvms(this);
Node *iffalse = _gvn.transform( new IfFalseNode (iff) );
set_control( iffalse );
- profile_switch_case(prof_table_index);
- merge_new_path(dest_bci_if_true);
+ if (unc) {
+ repush_if_args();
+ uncommon_trap(Deoptimization::Reason_unstable_if,
+ Deoptimization::Action_reinterpret,
+ NULL,
+ "taken never");
+ } else {
+ assert(dest_bci_if_true != never_reached, "inconsistent dest");
+ profile_switch_case(prof_table_index);
+ merge_new_path(dest_bci_if_true);
+ }
}
// False branch
@@ -235,10 +256,19 @@
set_control( iftrue );
}
-void Parse::jump_if_always_fork(int dest_bci, int prof_table_index) {
+void Parse::jump_if_always_fork(int dest_bci, int prof_table_index, bool unc) {
// False branch, use existing map and control()
- profile_switch_case(prof_table_index);
- merge_new_path(dest_bci);
+ if (unc) {
+ repush_if_args();
+ uncommon_trap(Deoptimization::Reason_unstable_if,
+ Deoptimization::Action_reinterpret,
+ NULL,
+ "taken never");
+ } else {
+ assert(dest_bci != never_reached, "inconsistent dest");
+ profile_switch_case(prof_table_index);
+ merge_new_path(dest_bci);
+ }
}
@@ -261,6 +291,7 @@
jint _hi; // inclusive upper limit
int _dest;
int _table_index; // index into method data table
+ float _cnt; // how many times this range was hit according to profiling
public:
jint lo() const { return _lo; }
@@ -268,44 +299,111 @@
int dest() const { return _dest; }
int table_index() const { return _table_index; }
bool is_singleton() const { return _lo == _hi; }
+ float cnt() const { return _cnt; }
- void setRange(jint lo, jint hi, int dest, int table_index) {
+ void setRange(jint lo, jint hi, int dest, int table_index, float cnt) {
assert(lo <= hi, "must be a non-empty range");
- _lo = lo, _hi = hi; _dest = dest; _table_index = table_index;
+ _lo = lo, _hi = hi; _dest = dest; _table_index = table_index; _cnt = cnt;
+ assert(_cnt >= 0, "");
}
- bool adjoinRange(jint lo, jint hi, int dest, int table_index) {
+ bool adjoinRange(jint lo, jint hi, int dest, int table_index, float cnt, bool trim_ranges) {
assert(lo <= hi, "must be a non-empty range");
- if (lo == _hi+1 && dest == _dest && table_index == _table_index) {
+ if (lo == _hi+1 && table_index == _table_index) {
+ // see merge_ranges() comment below
+ if (trim_ranges) {
+ if (cnt == 0) {
+ if (_cnt != 0) {
+ return false;
+ }
+ if (dest != _dest) {
+ _dest = never_reached;
+ }
+ } else {
+ if (_cnt == 0) {
+ return false;
+ }
+ if (dest != _dest) {
+ return false;
+ }
+ }
+ } else {
+ if (dest != _dest) {
+ return false;
+ }
+ }
_hi = hi;
+ _cnt += cnt;
return true;
}
return false;
}
- void set (jint value, int dest, int table_index) {
- setRange(value, value, dest, table_index);
+ void set (jint value, int dest, int table_index, float cnt) {
+ setRange(value, value, dest, table_index, cnt);
}
- bool adjoin(jint value, int dest, int table_index) {
- return adjoinRange(value, value, dest, table_index);
+ bool adjoin(jint value, int dest, int table_index, float cnt, bool trim_ranges) {
+ return adjoinRange(value, value, dest, table_index, cnt, trim_ranges);
+ }
+ bool adjoin(SwitchRange& other) {
+ return adjoinRange(other._lo, other._hi, other._dest, other._table_index, other._cnt, false);
}
void print() {
if (is_singleton())
- tty->print(" {%d}=>%d", lo(), dest());
+ tty->print(" {%d}=>%d (cnt=%f)", lo(), dest(), cnt());
else if (lo() == min_jint)
- tty->print(" {..%d}=>%d", hi(), dest());
+ tty->print(" {..%d}=>%d (cnt=%f)", hi(), dest(), cnt());
else if (hi() == max_jint)
- tty->print(" {%d..}=>%d", lo(), dest());
+ tty->print(" {%d..}=>%d (cnt=%f)", lo(), dest(), cnt());
else
- tty->print(" {%d..%d}=>%d", lo(), hi(), dest());
+ tty->print(" {%d..%d}=>%d (cnt=%f)", lo(), hi(), dest(), cnt());
}
};
+// We try to minimize the number of ranges and the size of the taken
+// ones using profiling data. When ranges are created,
+// SwitchRange::adjoinRange() only allows 2 adjoining ranges to merge
+// if both were never hit or both were hit to build longer unreached
+// ranges. Here, we now merge adjoining ranges with the same
+// destination and finally set destination of unreached ranges to the
+// special value never_reached because it can help minimize the number
+// of tests that are necessary.
+//
+// For instance:
+// [0, 1] to target1 sometimes taken
+// [1, 2] to target1 never taken
+// [2, 3] to target2 never taken
+// would lead to:
+// [0, 1] to target1 sometimes taken
+// [1, 3] never taken
+//
+// (first 2 ranges to target1 are not merged)
+static void merge_ranges(SwitchRange* ranges, int& rp) {
+ if (rp == 0) {
+ return;
+ }
+ int shift = 0;
+ for (int j = 0; j < rp; j++) {
+ SwitchRange& r1 = ranges[j-shift];
+ SwitchRange& r2 = ranges[j+1];
+ if (r1.adjoin(r2)) {
+ shift++;
+ } else if (shift > 0) {
+ ranges[j+1-shift] = r2;
+ }
+ }
+ rp -= shift;
+ for (int j = 0; j <= rp; j++) {
+ SwitchRange& r = ranges[j];
+ if (r.cnt() == 0 && r.dest() != never_reached) {
+ r.setRange(r.lo(), r.hi(), never_reached, r.table_index(), r.cnt());
+ }
+ }
+}
//-------------------------------do_tableswitch--------------------------------
void Parse::do_tableswitch() {
Node* lookup = pop();
-
// Get information about tableswitch
int default_dest = iter().get_dest_table(0);
int lo_index = iter().get_int_table(1);
@@ -319,31 +417,58 @@
return;
}
+ ciMethodData* methodData = method()->method_data();
+ ciMultiBranchData* profile = NULL;
+ if (methodData->is_mature() && UseSwitchProfiling) {
+ ciProfileData* data = methodData->bci_to_data(bci());
+ if (data != NULL && data->is_MultiBranchData()) {
+ profile = (ciMultiBranchData*)data;
+ }
+ }
+ bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
+
// generate decision tree, using trichotomy when possible
int rnum = len+2;
bool makes_backward_branch = false;
SwitchRange* ranges = NEW_RESOURCE_ARRAY(SwitchRange, rnum);
int rp = -1;
if (lo_index != min_jint) {
- ranges[++rp].setRange(min_jint, lo_index-1, default_dest, NullTableIndex);
+ uint cnt = 1;
+ if (profile != NULL) {
+ cnt = profile->default_count() / (hi_index != max_jint ? 2 : 1);
+ }
+ ranges[++rp].setRange(min_jint, lo_index-1, default_dest, NullTableIndex, cnt);
}
for (int j = 0; j < len; j++) {
jint match_int = lo_index+j;
int dest = iter().get_dest_table(j+3);
makes_backward_branch |= (dest <= bci());
int table_index = method_data_update() ? j : NullTableIndex;
- if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index)) {
- ranges[++rp].set(match_int, dest, table_index);
+ uint cnt = 1;
+ if (profile != NULL) {
+ cnt = profile->count_at(j);
+ }
+ if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index, cnt, trim_ranges)) {
+ ranges[++rp].set(match_int, dest, table_index, cnt);
}
}
jint highest = lo_index+(len-1);
assert(ranges[rp].hi() == highest, "");
- if (highest != max_jint
- && !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex)) {
- ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex);
+ if (highest != max_jint) {
+ uint cnt = 1;
+ if (profile != NULL) {
+ cnt = profile->default_count() / (lo_index != min_jint ? 2 : 1);
+ }
+ if (!ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex, cnt, trim_ranges)) {
+ ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex, cnt);
+ }
}
assert(rp < len+2, "not too many ranges");
+ if (trim_ranges) {
+ merge_ranges(ranges, rp);
+ }
+
// Safepoint in case if backward branch observed
if( makes_backward_branch && UseLoopSafepoints )
add_safepoint();
@@ -365,48 +490,263 @@
return;
}
+ ciMethodData* methodData = method()->method_data();
+ ciMultiBranchData* profile = NULL;
+ if (methodData->is_mature() && UseSwitchProfiling) {
+ ciProfileData* data = methodData->bci_to_data(bci());
+ if (data != NULL && data->is_MultiBranchData()) {
+ profile = (ciMultiBranchData*)data;
+ }
+ }
+ bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
+
// generate decision tree, using trichotomy when possible
- jint* table = NEW_RESOURCE_ARRAY(jint, len*2);
+ jint* table = NEW_RESOURCE_ARRAY(jint, len*3);
{
- for( int j = 0; j < len; j++ ) {
- table[j+j+0] = iter().get_int_table(2+j+j);
- table[j+j+1] = iter().get_dest_table(2+j+j+1);
+ for (int j = 0; j < len; j++) {
+ table[3*j+0] = iter().get_int_table(2+2*j);
+ table[3*j+1] = iter().get_dest_table(2+2*j+1);
+ table[3*j+2] = profile == NULL ? 1 : profile->count_at(j);
}
- qsort( table, len, 2*sizeof(table[0]), jint_cmp );
+ qsort(table, len, 3*sizeof(table[0]), jint_cmp);
+ }
+
+ float defaults = 0;
+ jint prev = min_jint;
+ for (int j = 0; j < len; j++) {
+ jint match_int = table[3*j+0];
+ if (match_int != prev) {
+ defaults += (float)match_int - prev;
+ }
+ prev = match_int+1;
+ }
+ if (prev-1 != max_jint) {
+ defaults += (float)max_jint - prev + 1;
+ }
+ float default_cnt = 1;
+ if (profile != NULL) {
+ default_cnt = profile->default_count()/defaults;
}
int rnum = len*2+1;
bool makes_backward_branch = false;
SwitchRange* ranges = NEW_RESOURCE_ARRAY(SwitchRange, rnum);
int rp = -1;
- for( int j = 0; j < len; j++ ) {
- jint match_int = table[j+j+0];
- int dest = table[j+j+1];
+ for (int j = 0; j < len; j++) {
+ jint match_int = table[3*j+0];
+ int dest = table[3*j+1];
+ int cnt = table[3*j+2];
int next_lo = rp < 0 ? min_jint : ranges[rp].hi()+1;
int table_index = method_data_update() ? j : NullTableIndex;
makes_backward_branch |= (dest <= bci());
- if( match_int != next_lo ) {
- ranges[++rp].setRange(next_lo, match_int-1, default_dest, NullTableIndex);
+ float c = default_cnt * ((float)match_int - next_lo);
+ if (match_int != next_lo && (rp < 0 || !ranges[rp].adjoinRange(next_lo, match_int-1, default_dest, NullTableIndex, c, trim_ranges))) {
+ assert(default_dest != never_reached, "sentinel value for dead destinations");
+ ranges[++rp].setRange(next_lo, match_int-1, default_dest, NullTableIndex, c);
}
- if( rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index) ) {
- ranges[++rp].set(match_int, dest, table_index);
+ if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index, cnt, trim_ranges)) {
+ assert(dest != never_reached, "sentinel value for dead destinations");
+ ranges[++rp].set(match_int, dest, table_index, cnt);
}
}
- jint highest = table[2*(len-1)];
+ jint highest = table[3*(len-1)];
assert(ranges[rp].hi() == highest, "");
- if( highest != max_jint
- && !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex) ) {
- ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex);
+ if (highest != max_jint &&
+ !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex, default_cnt * ((float)max_jint - highest), trim_ranges)) {
+ ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex, default_cnt * ((float)max_jint - highest));
}
assert(rp < rnum, "not too many ranges");
+ if (trim_ranges) {
+ merge_ranges(ranges, rp);
+ }
+
// Safepoint in case backward branch observed
- if( makes_backward_branch && UseLoopSafepoints )
+ if (makes_backward_branch && UseLoopSafepoints)
add_safepoint();
jump_switch_ranges(lookup, &ranges[0], &ranges[rp]);
}
+static float if_prob(float taken_cnt, float total_cnt) {
+ assert(taken_cnt <= total_cnt, "");
+ if (total_cnt == 0) {
+ return PROB_FAIR;
+ }
+ float p = taken_cnt / total_cnt;
+ return MIN2(MAX2(p, PROB_MIN), PROB_MAX);
+}
+
+static float if_cnt(float cnt) {
+ if (cnt == 0) {
+ return COUNT_UNKNOWN;
+ }
+ return cnt;
+}
+
+static float sum_of_cnts(SwitchRange *lo, SwitchRange *hi) {
+ float total_cnt = 0;
+ for (SwitchRange* sr = lo; sr <= hi; sr++) {
+ total_cnt += sr->cnt();
+ }
+ return total_cnt;
+}
+
+class SwitchRanges : public ResourceObj {
+public:
+ SwitchRange* _lo;
+ SwitchRange* _hi;
+ SwitchRange* _mid;
+ float _cost;
+
+ enum {
+ Start,
+ LeftDone,
+ RightDone,
+ Done
+ } _state;
+
+ SwitchRanges(SwitchRange *lo, SwitchRange *hi)
+ : _lo(lo), _hi(hi), _mid(NULL),
+ _cost(0), _state(Start) {
+ }
+
+ SwitchRanges()
+ : _lo(NULL), _hi(NULL), _mid(NULL),
+ _cost(0), _state(Start) {}
+};
+
+// Estimate cost of performing a binary search on lo..hi
+static float compute_tree_cost(SwitchRange *lo, SwitchRange *hi, float total_cnt) {
+ GrowableArray<SwitchRanges> tree;
+ SwitchRanges root(lo, hi);
+ tree.push(root);
+
+ float cost = 0;
+ do {
+ SwitchRanges& r = *tree.adr_at(tree.length()-1);
+ if (r._hi != r._lo) {
+ if (r._mid == NULL) {
+ float r_cnt = sum_of_cnts(r._lo, r._hi);
+
+ if (r_cnt == 0) {
+ tree.pop();
+ cost = 0;
+ continue;
+ }
+
+ SwitchRange* mid = NULL;
+ mid = r._lo;
+ for (float cnt = 0; ; ) {
+ assert(mid <= r._hi, "out of bounds");
+ cnt += mid->cnt();
+ if (cnt > r_cnt / 2) {
+ break;
+ }
+ mid++;
+ }
+ assert(mid <= r._hi, "out of bounds");
+ r._mid = mid;
+ r._cost = r_cnt / total_cnt;
+ }
+ r._cost += cost;
+ if (r._state < SwitchRanges::LeftDone && r._mid > r._lo) {
+ cost = 0;
+ r._state = SwitchRanges::LeftDone;
+ tree.push(SwitchRanges(r._lo, r._mid-1));
+ } else if (r._state < SwitchRanges::RightDone) {
+ cost = 0;
+ r._state = SwitchRanges::RightDone;
+ tree.push(SwitchRanges(r._mid == r._lo ? r._mid+1 : r._mid, r._hi));
+ } else {
+ tree.pop();
+ cost = r._cost;
+ }
+ } else {
+ tree.pop();
+ cost = r._cost;
+ }
+ } while (tree.length() > 0);
+
+
+ return cost;
+}
+
+// It sometimes pays off to test most common ranges before the binary search
+void Parse::linear_search_switch_ranges(Node* key_val, SwitchRange*& lo, SwitchRange*& hi) {
+ uint nr = hi - lo + 1;
+ float total_cnt = sum_of_cnts(lo, hi);
+
+ float min = compute_tree_cost(lo, hi, total_cnt);
+ float extra = 1;
+ float sub = 0;
+
+ SwitchRange* array1 = lo;
+ SwitchRange* array2 = NEW_RESOURCE_ARRAY(SwitchRange, nr);
+
+ SwitchRange* ranges = NULL;
+
+ while (nr >= 2) {
+ assert(lo == array1 || lo == array2, "one the 2 already allocated arrays");
+ ranges = (lo == array1) ? array2 : array1;
+
+ // Find highest frequency range
+ SwitchRange* candidate = lo;
+ for (SwitchRange* sr = lo+1; sr <= hi; sr++) {
+ if (sr->cnt() > candidate->cnt()) {
+ candidate = sr;
+ }
+ }
+ SwitchRange most_freq = *candidate;
+ if (most_freq.cnt() == 0) {
+ break;
+ }
+
+ // Copy remaining ranges into another array
+ int shift = 0;
+ for (uint i = 0; i < nr; i++) {
+ SwitchRange* sr = &lo[i];
+ if (sr != candidate) {
+ ranges[i-shift] = *sr;
+ } else {
+ shift++;
+ if (i > 0 && i < nr-1) {
+ SwitchRange prev = lo[i-1];
+ prev.setRange(prev.lo(), sr->hi(), prev.dest(), prev.table_index(), prev.cnt());
+ if (prev.adjoin(lo[i+1])) {
+ shift++;
+ i++;
+ }
+ ranges[i-shift] = prev;
+ }
+ }
+ }
+ nr -= shift;
+
+ // Evaluate cost of testing the most common range and performing a
+ // binary search on the other ranges
+ float cost = extra + compute_tree_cost(&ranges[0], &ranges[nr-1], total_cnt);
+ if (cost >= min) {
+ break;
+ }
+ // swap arrays
+ lo = &ranges[0];
+ hi = &ranges[nr-1];
+
+ // It pays off: emit the test for the most common range
+ assert(most_freq.cnt() > 0, "must be taken");
+ Node* val = _gvn.transform(new SubINode(key_val, _gvn.intcon(most_freq.lo())));
+ Node* cmp = _gvn.transform(new CmpUNode(val, _gvn.intcon(most_freq.hi() - most_freq.lo())));
+ Node* tst = _gvn.transform(new BoolNode(cmp, BoolTest::le));
+ IfNode* iff = create_and_map_if(control(), tst, if_prob(most_freq.cnt(), total_cnt), if_cnt(most_freq.cnt()));
+ jump_if_true_fork(iff, most_freq.dest(), most_freq.table_index(), false);
+
+ sub += most_freq.cnt() / total_cnt;
+ extra += 1 - sub;
+ min = cost;
+ }
+}
+
//----------------------------create_jump_tables-------------------------------
bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi) {
// Are jumptables enabled
@@ -418,6 +758,8 @@
// Don't make jump table if profiling
if (method_data_update()) return false;
+ bool trim_ranges = !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
+
// Decide if a guard is needed to lop off big ranges at either (or
// both) end(s) of the input set. We'll call this the default target
// even though we can't be sure that it is the true "default".
@@ -439,12 +781,22 @@
default_dest = hi->dest();
}
+ float total = sum_of_cnts(lo, hi);
+ float cost = compute_tree_cost(lo, hi, total);
+
// If a guard test will eliminate very sparse end ranges, then
// it is worth the cost of an extra jump.
+ float trimmed_cnt = 0;
if (total_outlier_size > (MaxJumpTableSparseness * 4)) {
needs_guard = true;
- if (default_dest == lo->dest()) lo++;
- if (default_dest == hi->dest()) hi--;
+ if (default_dest == lo->dest()) {
+ trimmed_cnt += lo->cnt();
+ lo++;
+ }
+ if (default_dest == hi->dest()) {
+ trimmed_cnt += hi->cnt();
+ hi--;
+ }
}
// Find the total number of cases and ranges
@@ -452,8 +804,23 @@
int num_range = hi - lo + 1;
// Don't create table if: too large, too small, or too sparse.
- if (num_cases < MinJumpTableSize || num_cases > MaxJumpTableSize)
+ if (num_cases > MaxJumpTableSize)
return false;
+ if (UseSwitchProfiling) {
+ // MinJumpTableSize is set so with a well balanced binary tree,
+ // when the number of ranges is MinJumpTableSize, it's cheaper to
+ // go through a JumpNode that a tree of IfNodes. Average cost of a
+ // tree of IfNodes with MinJumpTableSize is
+ // log2f(MinJumpTableSize) comparisons. So if the cost computed
+ // from profile data is less than log2f(MinJumpTableSize) then
+ // going with the binary search is cheaper.
+ if (cost < log2f(MinJumpTableSize)) {
+ return false;
+ }
+ } else {
+ if (num_cases < MinJumpTableSize)
+ return false;
+ }
if (num_cases > (MaxJumpTableSparseness * num_range))
return false;
@@ -465,10 +832,12 @@
// in the switch domain.
if (needs_guard) {
Node* size = _gvn.intcon(num_cases);
- Node* cmp = _gvn.transform( new CmpUNode(key_val, size) );
- Node* tst = _gvn.transform( new BoolNode(cmp, BoolTest::ge) );
- IfNode* iff = create_and_map_if( control(), tst, PROB_FAIR, COUNT_UNKNOWN);
- jump_if_true_fork(iff, default_dest, NullTableIndex);
+ Node* cmp = _gvn.transform(new CmpUNode(key_val, size));
+ Node* tst = _gvn.transform(new BoolNode(cmp, BoolTest::ge));
+ IfNode* iff = create_and_map_if(control(), tst, if_prob(trimmed_cnt, total), if_cnt(trimmed_cnt));
+ jump_if_true_fork(iff, default_dest, NullTableIndex, trim_ranges && trimmed_cnt == 0);
+
+ total -= trimmed_cnt;
}
// Create an ideal node JumpTable that has projections
@@ -489,17 +858,44 @@
key_val = _gvn.transform( new MulXNode( key_val, shiftWord));
// Create the JumpNode
- Node* jtn = _gvn.transform( new JumpNode(control(), key_val, num_cases) );
+ Arena* arena = C->comp_arena();
+ float* probs = (float*)arena->Amalloc(sizeof(float)*num_cases);
+ int i = 0;
+ if (total == 0) {
+ for (SwitchRange* r = lo; r <= hi; r++) {
+ for (int64_t j = r->lo(); j <= r->hi(); j++, i++) {
+ probs[i] = 1.0F / num_cases;
+ }
+ }
+ } else {
+ for (SwitchRange* r = lo; r <= hi; r++) {
+ float prob = r->cnt()/total;
+ for (int64_t j = r->lo(); j <= r->hi(); j++, i++) {
+ probs[i] = prob / (r->hi() - r->lo() + 1);
+ }
+ }
+ }
+
+ ciMethodData* methodData = method()->method_data();
+ ciMultiBranchData* profile = NULL;
+ if (methodData->is_mature()) {
+ ciProfileData* data = methodData->bci_to_data(bci());
+ if (data != NULL && data->is_MultiBranchData()) {
+ profile = (ciMultiBranchData*)data;
+ }
+ }
+
+ Node* jtn = _gvn.transform(new JumpNode(control(), key_val, num_cases, probs, profile == NULL ? COUNT_UNKNOWN : total));
// These are the switch destinations hanging off the jumpnode
- int i = 0;
+ i = 0;
for (SwitchRange* r = lo; r <= hi; r++) {
for (int64_t j = r->lo(); j <= r->hi(); j++, i++) {
Node* input = _gvn.transform(new JumpProjNode(jtn, i, r->dest(), (int)(j - lowval)));
{
PreserveJVMState pjvms(this);
set_control(input);
- jump_if_always_fork(r->dest(), r->table_index());
+ jump_if_always_fork(r->dest(), r->table_index(), trim_ranges && r->cnt() == 0);
}
}
}
@@ -511,6 +907,7 @@
//----------------------------jump_switch_ranges-------------------------------
void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, int switch_depth) {
Block* switch_block = block();
+ bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
if (switch_depth == 0) {
// Do special processing for the top-level call.
@@ -519,21 +916,23 @@
// Decrement pred-numbers for the unique set of nodes.
#ifdef ASSERT
- // Ensure that the block's successors are a (duplicate-free) set.
- int successors_counted = 0; // block occurrences in [hi..lo]
- int unique_successors = switch_block->num_successors();
- for (int i = 0; i < unique_successors; i++) {
- Block* target = switch_block->successor_at(i);
+ if (!trim_ranges) {
+ // Ensure that the block's successors are a (duplicate-free) set.
+ int successors_counted = 0; // block occurrences in [hi..lo]
+ int unique_successors = switch_block->num_successors();
+ for (int i = 0; i < unique_successors; i++) {
+ Block* target = switch_block->successor_at(i);
- // Check that the set of successors is the same in both places.
- int successors_found = 0;
- for (SwitchRange* p = lo; p <= hi; p++) {
- if (p->dest() == target->start()) successors_found++;
+ // Check that the set of successors is the same in both places.
+ int successors_found = 0;
+ for (SwitchRange* p = lo; p <= hi; p++) {
+ if (p->dest() == target->start()) successors_found++;
+ }
+ assert(successors_found > 0, "successor must be known");
+ successors_counted += successors_found;
}
- assert(successors_found > 0, "successor must be known");
- successors_counted += successors_found;
+ assert(successors_counted == (hi-lo)+1, "no unexpected successors");
}
- assert(successors_counted == (hi-lo)+1, "no unexpected successors");
#endif
// Maybe prune the inputs, based on the type of key_val.
@@ -545,10 +944,20 @@
max_val = ti->_hi;
assert(min_val <= max_val, "invalid int type");
}
- while (lo->hi() < min_val) lo++;
- if (lo->lo() < min_val) lo->setRange(min_val, lo->hi(), lo->dest(), lo->table_index());
- while (hi->lo() > max_val) hi--;
- if (hi->hi() > max_val) hi->setRange(hi->lo(), max_val, hi->dest(), hi->table_index());
+ while (lo->hi() < min_val) {
+ lo++;
+ }
+ if (lo->lo() < min_val) {
+ lo->setRange(min_val, lo->hi(), lo->dest(), lo->table_index(), lo->cnt());
+ }
+ while (hi->lo() > max_val) {
+ hi--;
+ }
+ if (hi->hi() > max_val) {
+ hi->setRange(hi->lo(), max_val, hi->dest(), hi->table_index(), hi->cnt());
+ }
+
+ linear_search_switch_ranges(key_val, lo, hi);
}
#ifndef PRODUCT
@@ -560,42 +969,57 @@
assert(lo <= hi, "must be a non-empty set of ranges");
if (lo == hi) {
- jump_if_always_fork(lo->dest(), lo->table_index());
+ jump_if_always_fork(lo->dest(), lo->table_index(), trim_ranges && lo->cnt() == 0);
} else {
assert(lo->hi() == (lo+1)->lo()-1, "contiguous ranges");
assert(hi->lo() == (hi-1)->hi()+1, "contiguous ranges");
if (create_jump_tables(key_val, lo, hi)) return;
- int nr = hi - lo + 1;
-
- SwitchRange* mid = lo + nr/2;
- // if there is an easy choice, pivot at a singleton:
- if (nr > 3 && !mid->is_singleton() && (mid-1)->is_singleton()) mid--;
+ SwitchRange* mid = NULL;
+ float total_cnt = sum_of_cnts(lo, hi);
- assert(lo < mid && mid <= hi, "good pivot choice");
- assert(nr != 2 || mid == hi, "should pick higher of 2");
- assert(nr != 3 || mid == hi-1, "should pick middle of 3");
+ int nr = hi - lo + 1;
+ if (UseSwitchProfiling) {
+ // Don't keep the binary search tree balanced: pick up mid point
+ // that split frequencies in half.
+ float cnt = 0;
+ for (SwitchRange* sr = lo; sr <= hi; sr++) {
+ cnt += sr->cnt();
+ if (cnt >= total_cnt / 2) {
+ mid = sr;
+ break;
+ }
+ }
+ } else {
+ mid = lo + nr/2;
- Node *test_val = _gvn.intcon(mid->lo());
+ // if there is an easy choice, pivot at a singleton:
+ if (nr > 3 && !mid->is_singleton() && (mid-1)->is_singleton()) mid--;
+
+ assert(lo < mid && mid <= hi, "good pivot choice");
+ assert(nr != 2 || mid == hi, "should pick higher of 2");
+ assert(nr != 3 || mid == hi-1, "should pick middle of 3");
+ }
+
+
+ Node *test_val = _gvn.intcon(mid == lo ? mid->hi() : mid->lo());
if (mid->is_singleton()) {
- IfNode *iff_ne = jump_if_fork_int(key_val, test_val, BoolTest::ne);
- jump_if_false_fork(iff_ne, mid->dest(), mid->table_index());
+ IfNode *iff_ne = jump_if_fork_int(key_val, test_val, BoolTest::ne, 1-if_prob(mid->cnt(), total_cnt), if_cnt(mid->cnt()));
+ jump_if_false_fork(iff_ne, mid->dest(), mid->table_index(), trim_ranges && mid->cnt() == 0);
// Special Case: If there are exactly three ranges, and the high
// and low range each go to the same place, omit the "gt" test,
// since it will not discriminate anything.
- bool eq_test_only = (hi == lo+2 && hi->dest() == lo->dest());
- if (eq_test_only) {
- assert(mid == hi-1, "");
- }
+ bool eq_test_only = (hi == lo+2 && hi->dest() == lo->dest() && mid == hi-1) || mid == lo;
// if there is a higher range, test for it and process it:
if (mid < hi && !eq_test_only) {
// two comparisons of same values--should enable 1 test for 2 branches
// Use BoolTest::le instead of BoolTest::gt
- IfNode *iff_le = jump_if_fork_int(key_val, test_val, BoolTest::le);
+ float cnt = sum_of_cnts(lo, mid-1);
+ IfNode *iff_le = jump_if_fork_int(key_val, test_val, BoolTest::le, if_prob(cnt, total_cnt), if_cnt(cnt));
Node *iftrue = _gvn.transform( new IfTrueNode(iff_le) );
Node *iffalse = _gvn.transform( new IfFalseNode(iff_le) );
{ PreserveJVMState pjvms(this);
@@ -607,24 +1031,33 @@
} else {
// mid is a range, not a singleton, so treat mid..hi as a unit
- IfNode *iff_ge = jump_if_fork_int(key_val, test_val, BoolTest::ge);
+ float cnt = sum_of_cnts(mid == lo ? mid+1 : mid, hi);
+ IfNode *iff_ge = jump_if_fork_int(key_val, test_val, mid == lo ? BoolTest::gt : BoolTest::ge, if_prob(cnt, total_cnt), if_cnt(cnt));
// if there is a higher range, test for it and process it:
if (mid == hi) {
- jump_if_true_fork(iff_ge, mid->dest(), mid->table_index());
+ jump_if_true_fork(iff_ge, mid->dest(), mid->table_index(), trim_ranges && cnt == 0);
} else {
Node *iftrue = _gvn.transform( new IfTrueNode(iff_ge) );
Node *iffalse = _gvn.transform( new IfFalseNode(iff_ge) );
{ PreserveJVMState pjvms(this);
set_control(iftrue);
- jump_switch_ranges(key_val, mid, hi, switch_depth+1);
+ jump_switch_ranges(key_val, mid == lo ? mid+1 : mid, hi, switch_depth+1);
}
set_control(iffalse);
}
}
// in any case, process the lower range
- jump_switch_ranges(key_val, lo, mid-1, switch_depth+1);
+ if (mid == lo) {
+ if (mid->is_singleton()) {
+ jump_switch_ranges(key_val, lo+1, hi, switch_depth+1);
+ } else {
+ jump_if_always_fork(lo->dest(), lo->table_index(), trim_ranges && lo->cnt() == 0);
+ }
+ } else {
+ jump_switch_ranges(key_val, lo, mid-1, switch_depth+1);
+ }
}
// Decrease pred_count for each successor after all is done.
@@ -724,7 +1157,7 @@
Node *mask = _gvn.intcon((divisor - 1));
// Sigh, must handle negative dividends
Node *zero = _gvn.intcon(0);
- IfNode *ifff = jump_if_fork_int(a, zero, BoolTest::lt);
+ IfNode *ifff = jump_if_fork_int(a, zero, BoolTest::lt, PROB_FAIR, COUNT_UNKNOWN);
Node *iff = _gvn.transform( new IfFalseNode(ifff) );
Node *ift = _gvn.transform( new IfTrueNode (ifff) );
Node *reg = jump_if_join(ift, iff);
--- a/src/hotspot/share/opto/superword.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/superword.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1943,9 +1943,14 @@
for (uint k = 0; k < use->req(); k++) {
Node* n = use->in(k);
if (def == n) {
- // reductions can be loop carried dependences
- if (def->is_reduction() && use->is_Phi())
+ // reductions should only have a Phi use at the the loop
+ // head and out of loop uses
+ if (def->is_reduction() &&
+ ((use->is_Phi() && use->in(0) == _lpt->_head) ||
+ !_lpt->is_member(_phase->get_loop(_phase->ctrl_or_self(use))))) {
+ assert(i == p->size()-1, "must be last element of the pack");
continue;
+ }
if (!is_vector_use(use, k)) {
return false;
}
--- a/src/hotspot/share/prims/whitebox.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/prims/whitebox.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1359,7 +1359,9 @@
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
- ::new (blob) BufferBlob("WB::DummyBlob", full_size);
+ if (blob != NULL) {
+ ::new (blob) BufferBlob("WB::DummyBlob", full_size);
+ }
}
// Track memory usage statistic after releasing CodeCache_lock
MemoryService::track_code_cache_memory_usage();
--- a/src/hotspot/share/runtime/arguments.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/runtime/arguments.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1821,18 +1821,6 @@
GCConfig::initialize();
-#if COMPILER2_OR_JVMCI
- // Shared spaces work fine with other GCs but causes bytecode rewriting
- // to be disabled, which hurts interpreter performance and decreases
- // server performance. When -server is specified, keep the default off
- // unless it is asked for. Future work: either add bytecode rewriting
- // at link time, or rewrite bytecodes in non-shared methods.
- if (is_server_compilation_mode_vm() && !DumpSharedSpaces && !RequireSharedSpaces &&
- (FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) {
- no_shared_spaces("COMPILER2 default: -Xshare:auto | off, have to manually setup to on.");
- }
-#endif
-
#if defined(IA32)
// Only server compiler can optimize safepoints well enough.
if (!is_server_compilation_mode_vm()) {
--- a/src/hotspot/share/runtime/globals.hpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/runtime/globals.hpp Thu Apr 26 17:59:02 2018 +0200
@@ -2997,6 +2997,8 @@
diagnostic(bool, ShowRegistersOnAssert, false, \
"On internal errors, include registers in error report.") \
\
+ experimental(bool, UseSwitchProfiling, true, \
+ "leverage profiling for table/lookup switch") \
#define VM_FLAGS(develop, \
develop_pd, \
--- a/src/hotspot/share/runtime/vmStructs.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/runtime/vmStructs.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -56,6 +56,7 @@
#include "memory/referenceType.hpp"
#include "memory/universe.hpp"
#include "memory/virtualspace.hpp"
+#include "memory/filemap.hpp"
#include "oops/array.hpp"
#include "oops/arrayKlass.hpp"
#include "oops/arrayOop.hpp"
@@ -1000,6 +1001,8 @@
c2_nonstatic_field(MachIfNode, _prob, jfloat) \
c2_nonstatic_field(MachIfNode, _fcnt, jfloat) \
\
+ c2_nonstatic_field(MachJumpNode, _probs, jfloat*) \
+ \
c2_nonstatic_field(CallNode, _entry_point, address) \
\
c2_nonstatic_field(CallJavaNode, _method, ciMethod*) \
@@ -1118,6 +1121,16 @@
static_field(java_lang_Class, _oop_size_offset, int) \
static_field(java_lang_Class, _static_oop_field_count_offset, int) \
\
+ /********************************************/ \
+ /* FileMapInfo fields (CDS archive related) */ \
+ /********************************************/ \
+ \
+ nonstatic_field(FileMapInfo, _header, FileMapInfo::FileMapHeader*) \
+ static_field(FileMapInfo, _current_info, FileMapInfo*) \
+ nonstatic_field(FileMapInfo::FileMapHeader, _space[0], FileMapInfo::FileMapHeader::space_info)\
+ nonstatic_field(FileMapInfo::FileMapHeader::space_info, _addr._base, char*) \
+ nonstatic_field(FileMapInfo::FileMapHeader::space_info, _used, size_t) \
+ \
/******************/ \
/* VMError fields */ \
/******************/ \
@@ -1442,7 +1455,7 @@
declare_type(SafepointBlob, SingletonBlob) \
declare_type(DeoptimizationBlob, SingletonBlob) \
declare_c2_type(ExceptionBlob, SingletonBlob) \
- declare_c2_type(UncommonTrapBlob, RuntimeBlob) \
+ declare_c2_type(UncommonTrapBlob, RuntimeBlob) \
\
/***************************************/ \
/* PcDesc and other compiled code info */ \
@@ -1663,6 +1676,7 @@
declare_c2_type(MachNullCheckNode, MachIdealNode) \
declare_c2_type(MachProjNode, ProjNode) \
declare_c2_type(MachIfNode, MachNode) \
+ declare_c2_type(MachJumpNode, MachNode) \
declare_c2_type(MachFastLockNode, MachNode) \
declare_c2_type(MachReturnNode, MachNode) \
declare_c2_type(MachSafePointNode, MachReturnNode) \
@@ -1997,6 +2011,10 @@
declare_toplevel_type(vframeArrayElement) \
declare_toplevel_type(Annotations*) \
declare_type(OopMapValue, StackObj) \
+ declare_type(FileMapInfo, CHeapObj<mtInternal>) \
+ declare_type(FileMapInfo::FileMapHeaderBase, CHeapObj<mtClass>) \
+ declare_type(FileMapInfo::FileMapHeader, FileMapInfo::FileMapHeaderBase)\
+ declare_toplevel_type(FileMapInfo::FileMapHeader::space_info) \
\
/************/ \
/* GC types */ \
--- a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m Thu Apr 26 17:59:02 2018 +0200
@@ -438,12 +438,11 @@
if (passwordChars == NULL) {
goto errOut;
}
- passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
- // clear the password and release
- memset(passwordChars, 0, passwordLen);
- (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
- JNI_ABORT);
+ passwordStrRef = CFStringCreateWithCharactersNoCopy(NULL, passwordChars, passwordLen, kCFAllocatorNull);
+ if (passwordStrRef == NULL) {
+ goto errOut;
+ }
}
}
@@ -471,7 +470,12 @@
errOut:
if (exportedData) CFRelease(exportedData);
if (passwordStrRef) CFRelease(passwordStrRef);
-
+ if (passwordChars) {
+ // clear the password and release
+ memset(passwordChars, 0, passwordLen);
+ (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
+ JNI_ABORT);
+ }
return returnValue;
}
@@ -538,12 +542,11 @@
if (passwordChars == NULL) {
goto errOut;
}
- passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
- // clear the password and release
- memset(passwordChars, 0, passwordLen);
- (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
- JNI_ABORT);
+ passwordStrRef = CFStringCreateWithCharactersNoCopy(NULL, passwordChars, passwordLen, kCFAllocatorNull);
+ if (passwordStrRef == NULL) {
+ goto errOut;
+ }
}
}
@@ -581,7 +584,14 @@
CFRelease(createdItems);
}
-errOut: ;
+errOut:
+ if (passwordStrRef) CFRelease(passwordStrRef);
+ if (passwordChars) {
+ // clear the password and release
+ memset(passwordChars, 0, passwordLen);
+ (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
+ JNI_ABORT);
+ }
JNF_COCOA_EXIT(env);
--- a/src/java.base/share/classes/java/io/FileInputStream.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/io/FileInputStream.java Thu Apr 26 17:59:02 2018 +0200
@@ -79,7 +79,7 @@
private volatile boolean closed;
- private final AltFinalizer altFinalizer;
+ private final Object altFinalizer;
/**
* Creates a <code>FileInputStream</code> by
@@ -155,7 +155,7 @@
fd.attach(this);
path = name;
open(name);
- altFinalizer = AltFinalizer.get(this);
+ altFinalizer = getFinalizer(this);
if (altFinalizer == null) {
FileCleanable.register(fd); // open set the fd, register the cleanup
}
@@ -471,6 +471,23 @@
protected void finalize() throws IOException {
}
+ /*
+ * Returns a finalizer object if the FIS needs a finalizer; otherwise null.
+ * If the FIS has a close method; it needs an AltFinalizer.
+ */
+ private static Object getFinalizer(FileInputStream fis) {
+ Class<?> clazz = fis.getClass();
+ while (clazz != FileInputStream.class) {
+ try {
+ clazz.getDeclaredMethod("close");
+ return new AltFinalizer(fis);
+ } catch (NoSuchMethodException nsme) {
+ // ignore
+ }
+ clazz = clazz.getSuperclass();
+ }
+ return null;
+ }
/**
* Class to call {@code FileInputStream.close} when finalized.
* If finalization of the stream is needed, an instance is created
@@ -481,25 +498,7 @@
static class AltFinalizer {
private final FileInputStream fis;
- /*
- * Returns a finalizer object if the FIS needs a finalizer; otherwise null.
- * If the FIS has a close method; it needs an AltFinalizer.
- */
- static AltFinalizer get(FileInputStream fis) {
- Class<?> clazz = fis.getClass();
- while (clazz != FileInputStream.class) {
- try {
- clazz.getDeclaredMethod("close");
- return new AltFinalizer(fis);
- } catch (NoSuchMethodException nsme) {
- // ignore
- }
- clazz = clazz.getSuperclass();
- }
- return null;
- }
-
- private AltFinalizer(FileInputStream fis) {
+ AltFinalizer(FileInputStream fis) {
this.fis = fis;
}
--- a/src/java.base/share/classes/java/io/FileOutputStream.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/io/FileOutputStream.java Thu Apr 26 17:59:02 2018 +0200
@@ -95,7 +95,7 @@
private volatile boolean closed;
- private final AltFinalizer altFinalizer;
+ private final Object altFinalizer;
/**
* Creates a file output stream to write to the file with the
@@ -235,7 +235,7 @@
this.path = name;
open(name, append);
- altFinalizer = AltFinalizer.get(this);
+ altFinalizer = getFinalizer(this);
if (altFinalizer == null) {
FileCleanable.register(fd); // open sets the fd, register the cleanup
}
@@ -496,6 +496,24 @@
initIDs();
}
+ /*
+ * Returns a finalizer object if the FOS needs a finalizer; otherwise null.
+ * If the FOS has a close method; it needs an AltFinalizer.
+ */
+ private static Object getFinalizer(FileOutputStream fos) {
+ Class<?> clazz = fos.getClass();
+ while (clazz != FileOutputStream.class) {
+ try {
+ clazz.getDeclaredMethod("close");
+ return new AltFinalizer(fos);
+ } catch (NoSuchMethodException nsme) {
+ // ignore
+ }
+ clazz = clazz.getSuperclass();
+ }
+ return null;
+ }
+
/**
* Class to call {@code FileOutputStream.close} when finalized.
* If finalization of the stream is needed, an instance is created
@@ -506,25 +524,7 @@
static class AltFinalizer {
private final FileOutputStream fos;
- /*
- * Returns a finalizer object if the FOS needs a finalizer; otherwise null.
- * If the FOS has a close method; it needs an AltFinalizer.
- */
- static AltFinalizer get(FileOutputStream fos) {
- Class<?> clazz = fos.getClass();
- while (clazz != FileOutputStream.class) {
- try {
- clazz.getDeclaredMethod("close");
- return new AltFinalizer(fos);
- } catch (NoSuchMethodException nsme) {
- // ignore
- }
- clazz = clazz.getSuperclass();
- }
- return null;
- }
-
- private AltFinalizer(FileOutputStream fos) {
+ AltFinalizer(FileOutputStream fos) {
this.fos = fos;
}
--- a/src/java.base/share/classes/java/lang/Long.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/lang/Long.java Thu Apr 26 17:59:02 2018 +0200
@@ -1164,10 +1164,8 @@
* significantly better space and time performance by caching
* frequently requested values.
*
- * Note that unlike the {@linkplain Integer#valueOf(int)
- * corresponding method} in the {@code Integer} class, this method
- * is <em>not</em> required to cache values within a particular
- * range.
+ * This method will always cache values in the range -128 to 127,
+ * inclusive, and may cache other values outside of this range.
*
* @param l a long value.
* @return a {@code Long} instance representing {@code l}.
--- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,13 +32,17 @@
import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.BytecodeName;
-import java.lang.reflect.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import static java.lang.invoke.LambdaForm.*;
@@ -64,7 +68,7 @@
private final List<MemberName> transformMethods;
private final MethodType baseConstructorType;
private final S topSpecies;
- private final ConcurrentMap<K, S> cache = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<K, S> cache = new ConcurrentHashMap<>();
private final Factory factory;
private @Stable boolean topClassIsSuper;
@@ -113,8 +117,7 @@
this.keyType = keyType;
this.metaType = metaType;
this.sdAccessor = sdAccessor;
- // FIXME: use List.copyOf once 8177290 is in
- this.transformMethods = List.of(transformMethods.toArray(new MemberName[transformMethods.size()]));
+ this.transformMethods = List.copyOf(transformMethods);
this.sdFieldName = sdFieldName;
this.baseConstructorType = baseConstructorType.changeReturnType(void.class);
this.factory = makeFactory();
@@ -149,12 +152,6 @@
}
public final S findSpecies(K key) {
- S speciesData = cache.computeIfAbsent(key, new Function<>() {
- @Override
- public S apply(K key1) {
- return factory.loadSpecies(newSpeciesData(key1));
- }
- });
// Note: Species instantiation may throw VirtualMachineError because of
// code cache overflow. If this happens the species bytecode may be
// loaded but not linked to its species metadata (with MH's etc).
@@ -176,7 +173,33 @@
// successfully on a concrete class if ever.
// The concrete class is published via SpeciesData instance
// returned here only after the class and species data are linked together.
- assert(speciesData != null);
+ S speciesData = cache.computeIfAbsent(key, new Function<>() {
+ @Override
+ public S apply(K key1) {
+ return newSpeciesData(key1);
+ }
+ });
+ // Separating the creation of a placeholder SpeciesData instance above
+ // from the loading and linking a real one below ensures we can never
+ // accidentally call computeIfAbsent recursively. Replacing rather than
+ // updating the placeholder is done to ensure safe publication.
+ if (!speciesData.isResolved()) {
+ synchronized (speciesData) {
+ S existingSpeciesData = cache.get(key);
+ if (existingSpeciesData == speciesData) { // won the race
+ // create a new SpeciesData...
+ speciesData = newSpeciesData(key);
+ // load and link it...
+ speciesData = factory.loadSpecies(speciesData);
+ if (!cache.replace(key, existingSpeciesData, speciesData)) {
+ throw newInternalError("Concurrent loadSpecies");
+ }
+ } else { // lost the race; the retrieved existingSpeciesData is the final
+ speciesData = existingSpeciesData;
+ }
+ }
+ }
+ assert(speciesData != null && speciesData.isResolved());
return speciesData;
}
@@ -208,9 +231,7 @@
protected SpeciesData(K key) {
this.key = keyType.cast(Objects.requireNonNull(key));
List<Class<?>> types = deriveFieldTypes(key);
- // TODO: List.copyOf
- int arity = types.size();
- this.fieldTypes = List.of(types.toArray(new Class<?>[arity]));
+ this.fieldTypes = List.copyOf(types);
}
public final K key() {
@@ -458,8 +479,8 @@
final Class<? extends T> speciesCode;
if (salvage != null) {
speciesCode = salvage.asSubclass(topClass());
- factory.linkSpeciesDataToCode(speciesData, speciesCode);
- factory.linkCodeToSpeciesData(speciesCode, speciesData, true);
+ linkSpeciesDataToCode(speciesData, speciesCode);
+ linkCodeToSpeciesData(speciesCode, speciesData, true);
} else {
// Not pregenerated, generate the class
try {
@@ -486,7 +507,7 @@
if (!speciesData.isResolved()) {
throw newInternalError("bad species class linkage for " + className + ": " + speciesData);
}
- assert(speciesData == factory.loadSpeciesDataFromCode(speciesCode));
+ assert(speciesData == loadSpeciesDataFromCode(speciesCode));
return speciesData;
}
--- a/src/java.base/share/classes/java/util/jar/Attributes.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/util/jar/Attributes.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,10 +28,10 @@
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collection;
-import java.util.Comparator;
+import java.util.HashMap;
import java.util.LinkedHashMap;
-import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import sun.util.logging.PlatformLogger;
@@ -116,7 +116,7 @@
* @throws IllegalArgumentException if the attribute name is invalid
*/
public String getValue(String name) {
- return (String)get(new Attributes.Name(name));
+ return (String)get(Name.of(name));
}
/**
@@ -168,7 +168,7 @@
* @exception IllegalArgumentException if the attribute name is invalid
*/
public String putValue(String name, String value) {
- return (String)put(new Name(name), value);
+ return (String)put(Name.of(name), value);
}
/**
@@ -371,7 +371,7 @@
*/
@SuppressWarnings("deprecation")
void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException {
- String name = null, value = null;
+ String name = null, value;
byte[] lastline = null;
int len;
@@ -447,8 +447,21 @@
* for more information about valid attribute names and values.
*/
public static class Name {
- private String name;
- private int hashCode = -1;
+ private final String name;
+ private final int hashCode;
+
+ /**
+ * Avoid allocation for common Names
+ */
+ private static final Map<String, Name> KNOWN_NAMES;
+
+ static final Name of(String name) {
+ Name n = KNOWN_NAMES.get(name);
+ if (n != null) {
+ return n;
+ }
+ return new Name(name);
+ }
/**
* Constructs a new attribute name using the given string name.
@@ -459,38 +472,33 @@
* @exception NullPointerException if the attribute name was null
*/
public Name(String name) {
- if (name == null) {
- throw new NullPointerException("name");
- }
- if (!isValid(name)) {
- throw new IllegalArgumentException(name);
- }
+ this.hashCode = hash(name);
this.name = name.intern();
}
- private static boolean isValid(String name) {
+ // Checks the string is valid
+ private final int hash(String name) {
+ Objects.requireNonNull(name, "name");
int len = name.length();
if (len > 70 || len == 0) {
- return false;
+ throw new IllegalArgumentException(name);
}
+ // Calculate hash code case insensitively
+ int h = 0;
for (int i = 0; i < len; i++) {
- if (!isValid(name.charAt(i))) {
- return false;
+ char c = name.charAt(i);
+ if (c >= 'a' && c <= 'z') {
+ // hashcode must be identical for upper and lower case
+ h = h * 31 + (c - 0x20);
+ } else if ((c >= 'A' && c <= 'Z' ||
+ c >= '0' && c <= '9' ||
+ c == '_' || c == '-')) {
+ h = h * 31 + c;
+ } else {
+ throw new IllegalArgumentException(name);
}
}
- return true;
- }
-
- private static boolean isValid(char c) {
- return isAlpha(c) || isDigit(c) || c == '_' || c == '-';
- }
-
- private static boolean isAlpha(char c) {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
- }
-
- private static boolean isDigit(char c) {
- return c >= '0' && c <= '9';
+ return h;
}
/**
@@ -500,9 +508,12 @@
* specified attribute object
*/
public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
if (o instanceof Name) {
- Comparator<String> c = String.CASE_INSENSITIVE_ORDER;
- return c.compare(name, ((Name)o).name) == 0;
+ Name other = (Name)o;
+ return other.name.equalsIgnoreCase(name);
} else {
return false;
}
@@ -512,9 +523,6 @@
* Computes the hash value for this attribute name.
*/
public int hashCode() {
- if (hashCode == -1) {
- hashCode = name.toLowerCase(Locale.ROOT).hashCode();
- }
return hashCode;
}
@@ -573,7 +581,7 @@
*/
public static final Name SEALED = new Name("Sealed");
- /**
+ /**
* {@code Name} object for {@code Extension-List} manifest attribute
* used for the extension mechanism that is no longer supported.
*/
@@ -620,7 +628,7 @@
@Deprecated
public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
- /**
+ /**
* {@code Name} object for {@code Implementation-URL}
* manifest attribute.
*
@@ -654,5 +662,55 @@
* @since 9
*/
public static final Name MULTI_RELEASE = new Name("Multi-Release");
+
+ private static void addName(Map<String, Name> names, Name name) {
+ names.put(name.name, name);
+ }
+
+ static {
+ var names = new HashMap<String, Name>(64);
+ addName(names, MANIFEST_VERSION);
+ addName(names, SIGNATURE_VERSION);
+ addName(names, CONTENT_TYPE);
+ addName(names, CLASS_PATH);
+ addName(names, MAIN_CLASS);
+ addName(names, SEALED);
+ addName(names, EXTENSION_LIST);
+ addName(names, EXTENSION_NAME);
+ addName(names, IMPLEMENTATION_TITLE);
+ addName(names, IMPLEMENTATION_VERSION);
+ addName(names, IMPLEMENTATION_VENDOR);
+ addName(names, SPECIFICATION_TITLE);
+ addName(names, SPECIFICATION_VERSION);
+ addName(names, SPECIFICATION_VENDOR);
+ addName(names, MULTI_RELEASE);
+
+ // Common attributes used in MANIFEST.MF et.al; adding these has a
+ // small footprint cost, but is likely to be quickly paid for by
+ // reducing allocation when reading and parsing typical manifests
+ addName(names, new Name("Add-Exports"));
+ addName(names, new Name("Add-Opens"));
+ addName(names, new Name("Ant-Version"));
+ addName(names, new Name("Archiver-Version"));
+ addName(names, new Name("Build-Jdk"));
+ addName(names, new Name("Built-By"));
+ addName(names, new Name("Bnd-LastModified"));
+ addName(names, new Name("Bundle-Description"));
+ addName(names, new Name("Bundle-DocURL"));
+ addName(names, new Name("Bundle-License"));
+ addName(names, new Name("Bundle-ManifestVersion"));
+ addName(names, new Name("Bundle-Name"));
+ addName(names, new Name("Bundle-Vendor"));
+ addName(names, new Name("Bundle-Version"));
+ addName(names, new Name("Bundle-SymbolicName"));
+ addName(names, new Name("Created-By"));
+ addName(names, new Name("Export-Package"));
+ addName(names, new Name("Import-Package"));
+ addName(names, new Name("Name"));
+ addName(names, new Name("SHA1-Digest"));
+ addName(names, new Name("X-Compile-Source-JDK"));
+ addName(names, new Name("X-Compile-Target-JDK"));
+ KNOWN_NAMES = names;
+ }
}
}
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -334,7 +334,7 @@
boolean append = fdAccess.getAppend(fd);
do {
// in append-mode then position is advanced to end before writing
- p = (append) ? nd.size(fd) : position0(fd, -1);
+ p = (append) ? nd.size(fd) : nd.seek(fd, -1);
} while ((p == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(p);
} finally {
@@ -358,7 +358,7 @@
if (!isOpen())
return null;
do {
- p = position0(fd, newPosition);
+ p = nd.seek(fd, newPosition);
} while ((p == IOStatus.INTERRUPTED) && isOpen());
return this;
} finally {
@@ -418,7 +418,7 @@
// get current position
do {
- p = position0(fd, -1);
+ p = nd.seek(fd, -1);
} while ((p == IOStatus.INTERRUPTED) && isOpen());
if (!isOpen())
return null;
@@ -437,7 +437,7 @@
if (p > newSize)
p = newSize;
do {
- rp = position0(fd, p);
+ rp = nd.seek(fd, p);
} while ((rp == IOStatus.INTERRUPTED) && isOpen());
return this;
} finally {
@@ -985,7 +985,7 @@
}
int rv;
do {
- rv = nd.allocate(fd, position + size);
+ rv = nd.truncate(fd, position + size);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
if (!isOpen())
return null;
@@ -1212,11 +1212,6 @@
private native long transferTo0(FileDescriptor src, long position,
long count, FileDescriptor dst);
- // Sets or reports this file's position
- // If offset is -1, the current position is returned
- // otherwise the position is set to offset
- private native long position0(FileDescriptor fd, long offset);
-
// Caches fieldIDs
private static native long initIDs();
--- a/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -36,12 +36,17 @@
public static final int RET_EX_LOCK = 1; // Obtained exclusive lock
public static final int INTERRUPTED = 2; // Request interrupted
+ /**
+ * Sets or reports this file's position
+ * If offset is -1, the current position is returned
+ * otherwise the position is set to offset.
+ */
+ abstract long seek(FileDescriptor fd, long offset) throws IOException;
+
abstract int force(FileDescriptor fd, boolean metaData) throws IOException;
abstract int truncate(FileDescriptor fd, long size) throws IOException;
- abstract int allocate(FileDescriptor fd, long size) throws IOException;
-
abstract long size(FileDescriptor fd) throws IOException;
abstract int lock(FileDescriptor fd, boolean blocking, long pos, long size,
--- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,7 @@
import java.io.FilePermission;
import java.net.SocketPermission;
import java.net.NetPermission;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.misc.JavaSecurityAccess;
import static jdk.internal.misc.JavaSecurityAccess.ProtectionDomainCache;
import jdk.internal.misc.SharedSecrets;
@@ -248,7 +248,8 @@
private static final int DEFAULT_CACHE_SIZE = 1;
// contains the policy grant entries, PD cache, and alias mapping
- private AtomicReference<PolicyInfo> policyInfo = new AtomicReference<>();
+ // can be updated if refresh() is called
+ private volatile PolicyInfo policyInfo;
private boolean expandProperties = true;
private boolean allowSystemProperties = true;
@@ -268,8 +269,8 @@
* previously parsed and have syntax errors, so that they can be
* subsequently ignored.
*/
- private static AtomicReference<Set<URL>> badPolicyURLs =
- new AtomicReference<>(new HashSet<>());
+ private static Set<URL> badPolicyURLs =
+ Collections.newSetFromMap(new ConcurrentHashMap<URL,Boolean>());
// The default.policy file
private static final URL DEFAULT_POLICY_URL =
@@ -341,7 +342,7 @@
// System.out.println("number caches=" + numCaches);
PolicyInfo newInfo = new PolicyInfo(numCaches);
initPolicyFile(newInfo, url);
- policyInfo.set(newInfo);
+ policyInfo = newInfo;
}
private void initPolicyFile(final PolicyInfo newInfo, final URL url) {
@@ -498,7 +499,7 @@
// skip parsing policy file if it has been previously parsed and
// has syntax errors
- if (badPolicyURLs.get().contains(policy)) {
+ if (badPolicyURLs.contains(policy)) {
if (debug != null) {
debug.println("skipping bad policy file: " + policy);
}
@@ -539,10 +540,7 @@
throw new InternalError("Failed to load default.policy", pe);
}
// record bad policy file to avoid later reparsing it
- badPolicyURLs.updateAndGet(k -> {
- k.add(policy);
- return k;
- });
+ badPolicyURLs.add(policy);
Object[] source = {policy, pe.getNonlocalizedMessage()};
System.err.println(LocalizedMessage.getNonlocalized
(POLICY + ".error.parsing.policy.message", source));
@@ -991,9 +989,7 @@
*/
@Override
public boolean implies(ProtectionDomain pd, Permission p) {
- PolicyInfo pi = policyInfo.get();
- ProtectionDomainCache pdMap = pi.getPdMapping();
-
+ ProtectionDomainCache pdMap = policyInfo.getPdMapping();
PermissionCollection pc = pdMap.get(pd);
if (pc != null) {
@@ -1139,9 +1135,7 @@
private Permissions getPermissions(Permissions perms,
final CodeSource cs,
Principal[] principals) {
- PolicyInfo pi = policyInfo.get();
-
- for (PolicyEntry entry : pi.policyEntries) {
+ for (PolicyEntry entry : policyInfo.policyEntries) {
addPermissions(perms, cs, principals, entry);
}
--- a/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -74,6 +74,10 @@
return writev0(fd, address, len);
}
+ long seek(FileDescriptor fd, long offset) throws IOException {
+ return seek0(fd, offset);
+ }
+
int force(FileDescriptor fd, boolean metaData) throws IOException {
return force0(fd, metaData);
}
@@ -82,10 +86,6 @@
return truncate0(fd, size);
}
- int allocate(FileDescriptor fd, long size) throws IOException {
- return allocate0(fd, size);
- }
-
long size(FileDescriptor fd) throws IOException {
return size0(fd);
}
@@ -156,10 +156,10 @@
static native int force0(FileDescriptor fd, boolean metaData)
throws IOException;
- static native int truncate0(FileDescriptor fd, long size)
+ static native long seek0(FileDescriptor fd, long offset)
throws IOException;
- static native int allocate0(FileDescriptor fd, long size)
+ static native int truncate0(FileDescriptor fd, long size)
throws IOException;
static native long size0(FileDescriptor fd) throws IOException;
--- a/src/java.base/unix/native/libjava/io_util_md.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/native/libjava/io_util_md.c Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -232,25 +232,6 @@
handleSetLength(FD fd, jlong length)
{
int result;
-#if defined(__linux__)
- /*
- * On Linux, if the file size is being increased, then ftruncate64()
- * will modify the metadata value of the size without actually allocating
- * any blocks which can cause a SIGBUS error if the file is subsequently
- * memory-mapped.
- */
- struct stat64 sb;
-
- if (fstat64(fd, &sb) == 0 && length > sb.st_blocks*512) {
- RESTARTABLE(fallocate64(fd, 0, 0, length), result);
- // Return on success or if errno is neither EOPNOTSUPP nor ENOSYS
- if (result == 0) {
- return 0;
- } else if (errno != EOPNOTSUPP && errno != ENOSYS) {
- return result;
- }
- }
-#endif
RESTARTABLE(ftruncate64(fd, length), result);
return result;
}
--- a/src/java.base/unix/native/libnio/ch/FileChannelImpl.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/native/libnio/ch/FileChannelImpl.c Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,33 +23,31 @@
* questions.
*/
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jvm_md.h"
-#include "jlong.h"
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include "sun_nio_ch_FileChannelImpl.h"
-#include "java_lang_Integer.h"
-#include "nio.h"
-#include "nio_util.h"
-#include <dlfcn.h>
+#include <sys/types.h>
+#include <unistd.h>
#if defined(__linux__) || defined(__solaris__)
#include <sys/sendfile.h>
#elif defined(_AIX)
#include <sys/socket.h>
#elif defined(_ALLBSD_SOURCE)
-#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
-
#define lseek64 lseek
#define mmap64 mmap
#endif
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "sun_nio_ch_FileChannelImpl.h"
+#include "java_lang_Integer.h"
+
static jfieldID chan_fd; /* jobject 'fd' in sun.nio.ch.FileChannelImpl */
JNIEXPORT jlong JNICALL
@@ -123,23 +121,6 @@
"Unmap failed");
}
-
-JNIEXPORT jlong JNICALL
-Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this,
- jobject fdo, jlong offset)
-{
- jint fd = fdval(env, fdo);
- jlong result = 0;
-
- if (offset < 0) {
- result = lseek64(fd, 0, SEEK_CUR);
- } else {
- result = lseek64(fd, offset, SEEK_SET);
- }
- return handle(env, result, "Position failed");
-}
-
-
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
jobject srcFDO,
--- a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,40 +23,42 @@
* questions.
*/
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "sun_nio_ch_FileDispatcherImpl.h"
-#include "java_lang_Long.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <unistd.h>
+#include <sys/stat.h>
#include <sys/statvfs.h>
+
#if defined(__linux__)
#include <linux/fs.h>
#include <sys/ioctl.h>
#endif
-#include "nio.h"
-#include "nio_util.h"
-#ifdef _ALLBSD_SOURCE
+#if defined(_ALLBSD_SOURCE)
+#define lseek64 lseek
#define stat64 stat
#define flock64 flock
#define off64_t off_t
#define F_SETLKW64 F_SETLKW
#define F_SETLK64 F_SETLK
-
#define pread64 pread
#define pwrite64 pwrite
#define ftruncate64 ftruncate
#define fstat64 fstat
-
#define fdatasync fsync
#endif
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "sun_nio_ch_FileDispatcherImpl.h"
+#include "java_lang_Long.h"
+
static int preCloseFD = -1; /* File descriptor to which we dup other fd's
before closing them for real */
@@ -142,6 +144,20 @@
return IOS_THROWN;
}
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_seek0(JNIEnv *env, jclass clazz,
+ jobject fdo, jlong offset)
+{
+ jint fd = fdval(env, fdo);
+ off64_t result;
+ if (offset < 0) {
+ result = lseek64(fd, 0, SEEK_CUR);
+ } else {
+ result = lseek64(fd, offset, SEEK_SET);
+ }
+ return handle(env, (jlong)result, "lseek64 failed");
+}
+
JNIEXPORT jint JNICALL
Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this,
jobject fdo, jboolean md)
@@ -187,30 +203,6 @@
"Truncation failed");
}
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_FileDispatcherImpl_allocate0(JNIEnv *env, jobject this,
- jobject fdo, jlong size)
-{
-#if defined(__linux__)
- /*
- * On Linux, if the file size is being increased, then ftruncate64()
- * will modify the metadata value of the size without actually allocating
- * any blocks which can cause a SIGBUS error if the file is subsequently
- * memory-mapped.
- */
- // Return on success or if errno is neither EOPNOTSUPP nor ENOSYS
- int result = fallocate64(fdval(env, fdo), 0, 0, size);
- if (result == 0) {
- return 0;
- } else if (errno != EOPNOTSUPP && errno != ENOSYS) {
- return handle(env, result, "Allocation failed");
- }
-#endif
- return handle(env,
- ftruncate64(fdval(env, fdo), size),
- "Truncation failed");
-}
-
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo)
{
--- a/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -69,7 +69,7 @@
if (fd == null)
throw new SocketException("Socket closed");
- int newfd = socketCreate(false /* v6Only */);
+ int newfd = socketCreate();
fdAccess.set(fd, newfd);
}
@@ -274,7 +274,7 @@
private static native void initIDs();
- private static native int socketCreate(boolean v6Only);
+ private static native int socketCreate();
private static native void socketBind(int fd, InetAddress localAddress,
int localport, boolean exclBind) throws SocketException;
--- a/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-/*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.net;
-
-import java.io.IOException;
-import java.io.FileDescriptor;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetPropertyAction;
-import jdk.internal.misc.SharedSecrets;
-import jdk.internal.misc.JavaIOFileDescriptorAccess;
-
-/**
- * This class defines the plain SocketImpl.
- * When java.net.preferIPv4Stack system property is set to true, it uses
- * IPv4-only socket.
- * When java.net.preferIPv4Stack is set to false, it handles both IPv4
- * and IPv6 through a single file descriptor.
- *
- * @author Chris Hegarty
- */
-
-class DualStackPlainSocketImpl extends AbstractPlainSocketImpl {
-
- private static final JavaIOFileDescriptorAccess fdAccess =
- SharedSecrets.getJavaIOFileDescriptorAccess();
-
- private static final boolean preferIPv4Stack =
- Boolean.parseBoolean(AccessController.doPrivileged(
- new GetPropertyAction("java.net.preferIPv4Stack", "false")));
-
- /**
- * Empty value of sun.net.useExclusiveBind is treated as 'true'.
- */
- private static final boolean useExclusiveBind;
-
- static {
- String exclBindProp = AccessController.doPrivileged(
- new GetPropertyAction("sun.net.useExclusiveBind", ""));
- useExclusiveBind = exclBindProp.isEmpty()
- || Boolean.parseBoolean(exclBindProp);
- }
-
- // emulates SO_REUSEADDR when useExclusiveBind is true
- private boolean isReuseAddress;
-
- public DualStackPlainSocketImpl() {
- }
-
- public DualStackPlainSocketImpl(FileDescriptor fd) {
- this.fd = fd;
- }
-
- @Override
- void socketCreate(boolean stream) throws IOException {
- if (fd == null)
- throw new SocketException("Socket closed");
-
- int newfd = socket0(stream);
-
- fdAccess.set(fd, newfd);
- }
-
- @Override
- void socketConnect(InetAddress address, int port, int timeout)
- throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (address == null)
- throw new NullPointerException("inet address argument is null.");
-
- if (preferIPv4Stack && !(address instanceof Inet4Address))
- throw new SocketException("Protocol family not supported");
-
- int connectResult;
- if (timeout <= 0) {
- connectResult = connect0(nativefd, address, port);
- } else {
- configureBlocking(nativefd, false);
- try {
- connectResult = connect0(nativefd, address, port);
- if (connectResult == WOULDBLOCK) {
- waitForConnect(nativefd, timeout);
- }
- } finally {
- configureBlocking(nativefd, true);
- }
- }
- /*
- * We need to set the local port field. If bind was called
- * previous to the connect (by the client) then localport field
- * will already be set.
- */
- if (localport == 0)
- localport = localPort0(nativefd);
- }
-
- @Override
- void socketBind(InetAddress address, int port) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (address == null)
- throw new NullPointerException("inet address argument is null.");
-
- if (preferIPv4Stack && !(address instanceof Inet4Address))
- throw new SocketException("Protocol family not supported");
-
- bind0(nativefd, address, port, useExclusiveBind);
- if (port == 0) {
- localport = localPort0(nativefd);
- } else {
- localport = port;
- }
-
- this.address = address;
- }
-
- @Override
- void socketListen(int backlog) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- listen0(nativefd, backlog);
- }
-
- @Override
- void socketAccept(SocketImpl s) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (s == null)
- throw new NullPointerException("socket is null");
-
- int newfd = -1;
- InetSocketAddress[] isaa = new InetSocketAddress[1];
- if (timeout <= 0) {
- newfd = accept0(nativefd, isaa);
- } else {
- configureBlocking(nativefd, false);
- try {
- waitForNewConnection(nativefd, timeout);
- newfd = accept0(nativefd, isaa);
- if (newfd != -1) {
- configureBlocking(newfd, true);
- }
- } finally {
- configureBlocking(nativefd, true);
- }
- }
- /* Update (SocketImpl)s' fd */
- fdAccess.set(s.fd, newfd);
- /* Update socketImpls remote port, address and localport */
- InetSocketAddress isa = isaa[0];
- s.port = isa.getPort();
- s.address = isa.getAddress();
- s.localport = localport;
- if (preferIPv4Stack && !(s.address instanceof Inet4Address))
- throw new SocketException("Protocol family not supported");
- }
-
- @Override
- int socketAvailable() throws IOException {
- int nativefd = checkAndReturnNativeFD();
- return available0(nativefd);
- }
-
- @Override
- void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
- if (fd == null)
- throw new SocketException("Socket closed");
-
- if (!fd.valid())
- return;
-
- final int nativefd = fdAccess.get(fd);
- fdAccess.set(fd, -1);
- close0(nativefd);
- }
-
- @Override
- void socketShutdown(int howto) throws IOException {
- int nativefd = checkAndReturnNativeFD();
- shutdown0(nativefd, howto);
- }
-
- // Intentional fallthrough after SO_REUSEADDR
- @SuppressWarnings("fallthrough")
- @Override
- void socketSetOption(int opt, boolean on, Object value)
- throws SocketException {
-
- // SO_REUSEPORT is not supported on Windows.
- if (opt == SO_REUSEPORT) {
- throw new UnsupportedOperationException("unsupported option");
- }
-
- int nativefd = checkAndReturnNativeFD();
-
- if (opt == SO_TIMEOUT) {
- if (preferIPv4Stack) {
- // Don't enable the socket option on ServerSocket as it's
- // meaningless (we don't receive on a ServerSocket).
- if (serverSocket == null) {
- setSoTimeout0(nativefd, ((Integer)value).intValue());
- }
- } // else timeout is implemented through select.
- return;
- }
-
- int optionValue = 0;
-
- switch(opt) {
- case SO_REUSEADDR:
- if (useExclusiveBind) {
- // SO_REUSEADDR emulated when using exclusive bind
- isReuseAddress = on;
- return;
- }
- // intentional fallthrough
- case TCP_NODELAY:
- case SO_OOBINLINE:
- case SO_KEEPALIVE:
- optionValue = on ? 1 : 0;
- break;
- case SO_SNDBUF:
- case SO_RCVBUF:
- case IP_TOS:
- optionValue = ((Integer)value).intValue();
- break;
- case SO_LINGER:
- if (on) {
- optionValue = ((Integer)value).intValue();
- } else {
- optionValue = -1;
- }
- break;
- default :/* shouldn't get here */
- throw new SocketException("Option not supported");
- }
-
- setIntOption(nativefd, opt, optionValue);
- }
-
- @Override
- int socketGetOption(int opt, Object iaContainerObj)
- throws SocketException {
-
- // SO_REUSEPORT is not supported on Windows.
- if (opt == SO_REUSEPORT) {
- throw new UnsupportedOperationException("unsupported option");
- }
-
- int nativefd = checkAndReturnNativeFD();
-
- // SO_BINDADDR is not a socket option.
- if (opt == SO_BINDADDR) {
- localAddress(nativefd, (InetAddressContainer)iaContainerObj);
- return 0; // return value doesn't matter.
- }
-
- // SO_REUSEADDR emulated when using exclusive bind
- if (opt == SO_REUSEADDR && useExclusiveBind)
- return isReuseAddress ? 1 : -1;
-
- int value = getIntOption(nativefd, opt);
-
- switch (opt) {
- case TCP_NODELAY:
- case SO_OOBINLINE:
- case SO_KEEPALIVE:
- case SO_REUSEADDR:
- return (value == 0) ? -1 : 1;
- }
- return value;
- }
-
- @Override
- void socketSendUrgentData(int data) throws IOException {
- int nativefd = checkAndReturnNativeFD();
- sendOOB(nativefd, data);
- }
-
- private int checkAndReturnNativeFD() throws SocketException {
- if (fd == null || !fd.valid())
- throw new SocketException("Socket closed");
-
- return fdAccess.get(fd);
- }
-
- static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
-
- static {
- initIDs();
- }
-
- /* Native methods */
-
- static native void initIDs();
-
- static native int socket0(boolean stream) throws IOException;
-
- static native void bind0(int fd, InetAddress localAddress, int localport,
- boolean exclBind)
- throws IOException;
-
- static native int connect0(int fd, InetAddress remote, int remotePort)
- throws IOException;
-
- static native void waitForConnect(int fd, int timeout) throws IOException;
-
- static native int localPort0(int fd) throws IOException;
-
- static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
-
- static native void listen0(int fd, int backlog) throws IOException;
-
- static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
-
- static native void waitForNewConnection(int fd, int timeout) throws IOException;
-
- static native int available0(int fd) throws IOException;
-
- static native void close0(int fd) throws IOException;
-
- static native void shutdown0(int fd, int howto) throws IOException;
-
- static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
-
- static native void setSoTimeout0(int fd, int timeout) throws SocketException;
-
- static native int getIntOption(int fd, int cmd) throws SocketException;
-
- static native void sendOOB(int fd, int data) throws IOException;
-
- static native void configureBlocking(int fd, boolean blocking) throws IOException;
-}
--- a/src/java.base/windows/classes/java/net/PlainSocketImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,261 +24,335 @@
*/
package java.net;
-import java.io.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.JavaIOFileDescriptorAccess;
-/*
- * This class PlainSocketImpl simply delegates to the appropriate real
- * SocketImpl. We do this because PlainSocketImpl is already extended
- * by SocksSocketImpl.
- * <p>
- * There is one possibility for the real SocketImpl: DualStackPlainSocketImpl.
+/**
+ * On Windows system we simply delegate to native methods.
*
* @author Chris Hegarty
*/
class PlainSocketImpl extends AbstractPlainSocketImpl {
- private AbstractPlainSocketImpl impl;
+
+ private static final JavaIOFileDescriptorAccess fdAccess =
+ SharedSecrets.getJavaIOFileDescriptorAccess();
+
+ private static final boolean preferIPv4Stack =
+ Boolean.parseBoolean(AccessController.doPrivileged(
+ new GetPropertyAction("java.net.preferIPv4Stack", "false")));
+
+ /**
+ * Empty value of sun.net.useExclusiveBind is treated as 'true'.
+ */
+ private static final boolean useExclusiveBind;
+
+ static {
+ String exclBindProp = AccessController.doPrivileged(
+ new GetPropertyAction("sun.net.useExclusiveBind", ""));
+ useExclusiveBind = exclBindProp.isEmpty()
+ || Boolean.parseBoolean(exclBindProp);
+ }
+
+ // emulates SO_REUSEADDR when useExclusiveBind is true
+ private boolean isReuseAddress;
/**
* Constructs an empty instance.
*/
- PlainSocketImpl() {
- impl = new DualStackPlainSocketImpl();
+ public PlainSocketImpl() {
}
/**
* Constructs an instance with the given file descriptor.
*/
- PlainSocketImpl(FileDescriptor fd) {
- impl = new DualStackPlainSocketImpl(fd);
- }
-
- // Override methods in SocketImpl that access impl's fields.
-
- protected FileDescriptor getFileDescriptor() {
- return impl.getFileDescriptor();
+ public PlainSocketImpl(FileDescriptor fd) {
+ this.fd = fd;
}
- protected InetAddress getInetAddress() {
- return impl.getInetAddress();
- }
+ @Override
+ void socketCreate(boolean stream) throws IOException {
+ if (fd == null)
+ throw new SocketException("Socket closed");
- protected int getPort() {
- return impl.getPort();
- }
+ int newfd = socket0(stream);
- protected int getLocalPort() {
- return impl.getLocalPort();
- }
-
- void setSocket(Socket soc) {
- impl.setSocket(soc);
+ fdAccess.set(fd, newfd);
}
- Socket getSocket() {
- return impl.getSocket();
- }
+ @Override
+ void socketConnect(InetAddress address, int port, int timeout)
+ throws IOException {
+ int nativefd = checkAndReturnNativeFD();
- void setServerSocket(ServerSocket soc) {
- impl.setServerSocket(soc);
- }
+ if (address == null)
+ throw new NullPointerException("inet address argument is null.");
- ServerSocket getServerSocket() {
- return impl.getServerSocket();
- }
+ if (preferIPv4Stack && !(address instanceof Inet4Address))
+ throw new SocketException("Protocol family not supported");
- public String toString() {
- return impl.toString();
- }
-
- // Override methods in AbstractPlainSocketImpl that access impl's fields.
-
- protected synchronized void create(boolean stream) throws IOException {
- impl.create(stream);
-
- // set fd to delegate's fd to be compatible with older releases
- this.fd = impl.fd;
- }
-
- protected void connect(String host, int port)
- throws UnknownHostException, IOException
- {
- impl.connect(host, port);
+ int connectResult;
+ if (timeout <= 0) {
+ connectResult = connect0(nativefd, address, port);
+ } else {
+ configureBlocking(nativefd, false);
+ try {
+ connectResult = connect0(nativefd, address, port);
+ if (connectResult == WOULDBLOCK) {
+ waitForConnect(nativefd, timeout);
+ }
+ } finally {
+ configureBlocking(nativefd, true);
+ }
+ }
+ /*
+ * We need to set the local port field. If bind was called
+ * previous to the connect (by the client) then localport field
+ * will already be set.
+ */
+ if (localport == 0)
+ localport = localPort0(nativefd);
}
- protected void connect(InetAddress address, int port) throws IOException {
- impl.connect(address, port);
- }
+ @Override
+ void socketBind(InetAddress address, int port) throws IOException {
+ int nativefd = checkAndReturnNativeFD();
+
+ if (address == null)
+ throw new NullPointerException("inet address argument is null.");
- protected void connect(SocketAddress address, int timeout) throws IOException {
- impl.connect(address, timeout);
- }
+ if (preferIPv4Stack && !(address instanceof Inet4Address))
+ throw new SocketException("Protocol family not supported");
- public void setOption(int opt, Object val) throws SocketException {
- impl.setOption(opt, val);
+ bind0(nativefd, address, port, useExclusiveBind);
+ if (port == 0) {
+ localport = localPort0(nativefd);
+ } else {
+ localport = port;
+ }
+
+ this.address = address;
}
- public Object getOption(int opt) throws SocketException {
- return impl.getOption(opt);
- }
+ @Override
+ void socketListen(int backlog) throws IOException {
+ int nativefd = checkAndReturnNativeFD();
- synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
- impl.doConnect(address, port, timeout);
- }
-
- protected synchronized void bind(InetAddress address, int lport)
- throws IOException
- {
- impl.bind(address, lport);
+ listen0(nativefd, backlog);
}
- protected synchronized void accept(SocketImpl s) throws IOException {
- if (s instanceof PlainSocketImpl) {
- // pass in the real impl not the wrapper.
- SocketImpl delegate = ((PlainSocketImpl)s).impl;
- delegate.address = new InetAddress();
- delegate.fd = new FileDescriptor();
- impl.accept(delegate);
- // set fd to delegate's fd to be compatible with older releases
- s.fd = delegate.fd;
+ @Override
+ void socketAccept(SocketImpl s) throws IOException {
+ int nativefd = checkAndReturnNativeFD();
+
+ if (s == null)
+ throw new NullPointerException("socket is null");
+
+ int newfd = -1;
+ InetSocketAddress[] isaa = new InetSocketAddress[1];
+ if (timeout <= 0) {
+ newfd = accept0(nativefd, isaa);
} else {
- impl.accept(s);
+ configureBlocking(nativefd, false);
+ try {
+ waitForNewConnection(nativefd, timeout);
+ newfd = accept0(nativefd, isaa);
+ if (newfd != -1) {
+ configureBlocking(newfd, true);
+ }
+ } finally {
+ configureBlocking(nativefd, true);
+ }
}
+ /* Update (SocketImpl)s' fd */
+ fdAccess.set(s.fd, newfd);
+ /* Update socketImpls remote port, address and localport */
+ InetSocketAddress isa = isaa[0];
+ s.port = isa.getPort();
+ s.address = isa.getAddress();
+ s.localport = localport;
+ if (preferIPv4Stack && !(s.address instanceof Inet4Address))
+ throw new SocketException("Protocol family not supported");
}
- void setFileDescriptor(FileDescriptor fd) {
- impl.setFileDescriptor(fd);
- }
-
- void setAddress(InetAddress address) {
- impl.setAddress(address);
+ @Override
+ int socketAvailable() throws IOException {
+ int nativefd = checkAndReturnNativeFD();
+ return available0(nativefd);
}
- void setPort(int port) {
- impl.setPort(port);
+ @Override
+ void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
+ if (fd == null)
+ throw new SocketException("Socket closed");
+
+ if (!fd.valid())
+ return;
+
+ final int nativefd = fdAccess.get(fd);
+ fdAccess.set(fd, -1);
+ close0(nativefd);
}
- void setLocalPort(int localPort) {
- impl.setLocalPort(localPort);
- }
-
- protected synchronized InputStream getInputStream() throws IOException {
- return impl.getInputStream();
+ @Override
+ void socketShutdown(int howto) throws IOException {
+ int nativefd = checkAndReturnNativeFD();
+ shutdown0(nativefd, howto);
}
- void setInputStream(SocketInputStream in) {
- impl.setInputStream(in);
- }
+ // Intentional fallthrough after SO_REUSEADDR
+ @SuppressWarnings("fallthrough")
+ @Override
+ void socketSetOption(int opt, boolean on, Object value)
+ throws SocketException {
- protected synchronized OutputStream getOutputStream() throws IOException {
- return impl.getOutputStream();
- }
+ // SO_REUSEPORT is not supported on Windows.
+ if (opt == SO_REUSEPORT) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+
+ int nativefd = checkAndReturnNativeFD();
- protected void close() throws IOException {
- try {
- impl.close();
- } finally {
- // set fd to delegate's fd to be compatible with older releases
- this.fd = null;
+ if (opt == SO_TIMEOUT) {
+ if (preferIPv4Stack) {
+ // Don't enable the socket option on ServerSocket as it's
+ // meaningless (we don't receive on a ServerSocket).
+ if (serverSocket == null) {
+ setSoTimeout0(nativefd, ((Integer)value).intValue());
+ }
+ } // else timeout is implemented through select.
+ return;
}
- }
- void reset() throws IOException {
- try {
- impl.reset();
- } finally {
- // set fd to delegate's fd to be compatible with older releases
- this.fd = null;
- }
- }
+ int optionValue = 0;
- protected void shutdownInput() throws IOException {
- impl.shutdownInput();
- }
-
- protected void shutdownOutput() throws IOException {
- impl.shutdownOutput();
- }
-
- protected void sendUrgentData(int data) throws IOException {
- impl.sendUrgentData(data);
- }
+ switch(opt) {
+ case SO_REUSEADDR:
+ if (useExclusiveBind) {
+ // SO_REUSEADDR emulated when using exclusive bind
+ isReuseAddress = on;
+ return;
+ }
+ // intentional fallthrough
+ case TCP_NODELAY:
+ case SO_OOBINLINE:
+ case SO_KEEPALIVE:
+ optionValue = on ? 1 : 0;
+ break;
+ case SO_SNDBUF:
+ case SO_RCVBUF:
+ case IP_TOS:
+ optionValue = ((Integer)value).intValue();
+ break;
+ case SO_LINGER:
+ if (on) {
+ optionValue = ((Integer)value).intValue();
+ } else {
+ optionValue = -1;
+ }
+ break;
+ default :/* shouldn't get here */
+ throw new SocketException("Option not supported");
+ }
- FileDescriptor acquireFD() {
- return impl.acquireFD();
- }
-
- void releaseFD() {
- impl.releaseFD();
- }
-
- boolean isConnectionReset() {
- return impl.isConnectionReset();
- }
-
- void setConnectionReset() {
- impl.setConnectionReset();
- }
-
- public boolean isClosedOrPending() {
- return impl.isClosedOrPending();
+ setIntOption(nativefd, opt, optionValue);
}
- public int getTimeout() {
- return impl.getTimeout();
- }
+ @Override
+ int socketGetOption(int opt, Object iaContainerObj)
+ throws SocketException {
+
+ // SO_REUSEPORT is not supported on Windows.
+ if (opt == SO_REUSEPORT) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+
+ int nativefd = checkAndReturnNativeFD();
- // Override methods in AbstractPlainSocketImpl that need to be implemented.
+ // SO_BINDADDR is not a socket option.
+ if (opt == SO_BINDADDR) {
+ localAddress(nativefd, (InetAddressContainer)iaContainerObj);
+ return 0; // return value doesn't matter.
+ }
+
+ // SO_REUSEADDR emulated when using exclusive bind
+ if (opt == SO_REUSEADDR && useExclusiveBind)
+ return isReuseAddress ? 1 : -1;
- void socketCreate(boolean stream) throws IOException {
- impl.socketCreate(stream);
+ int value = getIntOption(nativefd, opt);
+
+ switch (opt) {
+ case TCP_NODELAY:
+ case SO_OOBINLINE:
+ case SO_KEEPALIVE:
+ case SO_REUSEADDR:
+ return (value == 0) ? -1 : 1;
+ }
+ return value;
}
- void socketConnect(InetAddress address, int port, int timeout)
- throws IOException {
- impl.socketConnect(address, port, timeout);
+ @Override
+ void socketSendUrgentData(int data) throws IOException {
+ int nativefd = checkAndReturnNativeFD();
+ sendOOB(nativefd, data);
}
- void socketBind(InetAddress address, int port)
- throws IOException {
- impl.socketBind(address, port);
- }
+ private int checkAndReturnNativeFD() throws SocketException {
+ if (fd == null || !fd.valid())
+ throw new SocketException("Socket closed");
- void socketListen(int count) throws IOException {
- impl.socketListen(count);
- }
-
- void socketAccept(SocketImpl s) throws IOException {
- impl.socketAccept(s);
+ return fdAccess.get(fd);
}
- int socketAvailable() throws IOException {
- return impl.socketAvailable();
- }
+ static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
- void socketClose0(boolean useDeferredClose) throws IOException {
- impl.socketClose0(useDeferredClose);
- }
-
- void socketShutdown(int howto) throws IOException {
- impl.socketShutdown(howto);
+ static {
+ initIDs();
}
- void socketSetOption(int cmd, boolean on, Object value)
- throws SocketException {
- impl.socketSetOption(cmd, on, value);
- }
+ /* Native methods */
+
+ static native void initIDs();
+
+ static native int socket0(boolean stream) throws IOException;
+
+ static native void bind0(int fd, InetAddress localAddress, int localport,
+ boolean exclBind)
+ throws IOException;
- int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
- return impl.socketGetOption(opt, iaContainerObj);
- }
+ static native int connect0(int fd, InetAddress remote, int remotePort)
+ throws IOException;
+
+ static native void waitForConnect(int fd, int timeout) throws IOException;
+
+ static native int localPort0(int fd) throws IOException;
+
+ static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
+
+ static native void listen0(int fd, int backlog) throws IOException;
- void socketSendUrgentData(int data) throws IOException {
- impl.socketSendUrgentData(data);
- }
+ static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
+
+ static native void waitForNewConnection(int fd, int timeout) throws IOException;
+
+ static native int available0(int fd) throws IOException;
+
+ static native void close0(int fd) throws IOException;
+
+ static native void shutdown0(int fd, int howto) throws IOException;
- static boolean isReusePortAvailable() {
- // SO_REUSEPORT is not supported on Windows.
- return false;
- }
+ static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
+
+ static native void setSoTimeout0(int fd, int timeout) throws SocketException;
+
+ static native int getIntOption(int fd, int cmd) throws SocketException;
+
+ static native void sendOOB(int fd, int data) throws IOException;
+
+ static native void configureBlocking(int fd, boolean blocking) throws IOException;
}
--- a/src/java.base/windows/classes/sun/net/PortConfig.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/sun/net/PortConfig.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,49 +25,21 @@
package sun.net;
-import java.security.AccessController;
-
/**
* Determines the ephemeral port range in use on this system.
- * If this cannot be determined, then the default settings
- * of the OS are returned.
+ * On Windows we always use the default range.
*/
public final class PortConfig {
- private static int defaultUpper, defaultLower;
- private static final int upper, lower;
-
- static {
- AccessController.doPrivileged(
- new java.security.PrivilegedAction<Void>() {
- public Void run() {
- System.loadLibrary("net");
- return null;
- }
- });
-
- int v = getLower0();
- if (v == -1) {
- v = defaultLower;
- }
- lower = v;
-
- v = getUpper0();
- if (v == -1) {
- v = defaultUpper;
- }
- upper = v;
- }
-
- static native int getLower0();
- static native int getUpper0();
+ private static final int defaultLower = 49152;
+ private static final int defaultUpper = 65535;
public static int getLower() {
- return lower;
+ return defaultLower;
}
public static int getUpper() {
- return upper;
+ return defaultUpper;
}
}
--- a/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -78,6 +78,10 @@
return writev0(fd, address, len, fdAccess.getAppend(fd));
}
+ long seek(FileDescriptor fd, long offset) throws IOException {
+ return seek0(fd, offset);
+ }
+
int force(FileDescriptor fd, boolean metaData) throws IOException {
return force0(fd, metaData);
}
@@ -86,11 +90,6 @@
return truncate0(fd, size);
}
- int allocate(FileDescriptor fd, long size) throws IOException {
- // truncate0() works for extending and truncating file size
- return truncate0(fd, size);
- }
-
long size(FileDescriptor fd) throws IOException {
return size0(fd);
}
@@ -126,8 +125,7 @@
return true;
}
- int setDirectIO(FileDescriptor fd, String path)
- {
+ int setDirectIO(FileDescriptor fd, String path) {
int result = -1;
String filePath = path.substring(0, path.lastIndexOf(File.separator));
CharBuffer buffer = CharBuffer.allocate(filePath.length());
@@ -178,6 +176,8 @@
static native long writev0(FileDescriptor fd, long address, int len, boolean append)
throws IOException;
+ static native long seek0(FileDescriptor fd, long offset) throws IOException;
+
static native int force0(FileDescriptor fd, boolean metaData)
throws IOException;
--- a/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -92,10 +92,10 @@
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketCreate
- * Signature: (Z)I
+ * Signature: ()I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate
- (JNIEnv *env, jclass clazz, jboolean v6Only /*unused*/) {
+ (JNIEnv *env, jclass clazz) {
int fd, rv, opt=0, t=TRUE;
DWORD x1, x2; /* ignored result codes */
@@ -121,7 +121,7 @@
* when the socket is connected.
*/
t = FALSE;
- WSAIoctl(fd ,SIO_UDP_CONNRESET ,&t ,sizeof(t) ,&x1 ,sizeof(x1) ,&x2 ,0 ,0);
+ WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
return fd;
}
@@ -158,7 +158,7 @@
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
SOCKETADDRESS sa;
- int rv, sa_len = 0, t = TRUE;
+ int rv, sa_len = 0, t;
DWORD x1, x2; /* ignored result codes */
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
@@ -173,6 +173,7 @@
}
/* see comment in socketCreate */
+ t = TRUE;
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
}
--- a/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,534 +0,0 @@
-/*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-#include "net_util.h"
-
-#include "java_net_DualStackPlainSocketImpl.h"
-#include "java_net_SocketOptions.h"
-
-#define SET_BLOCKING 0
-#define SET_NONBLOCKING 1
-
-static jclass isa_class; /* java.net.InetSocketAddress */
-static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
- (JNIEnv *env, jclass clazz) {
-
- jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
- CHECK_NULL(cls);
- isa_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL(isa_class);
- isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
- "(Ljava/net/InetAddress;I)V");
- CHECK_NULL(isa_ctorID);
- initInetAddressIDs(env);
-
- // implement read timeout with select.
- isRcvTimeoutSupported = JNI_FALSE;
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: socket0
- * Signature: (ZZ)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
- (JNIEnv *env, jclass clazz, jboolean stream) {
- int fd, rv, opt=0;
- int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
- int domain = ipv6_available() ? AF_INET6 : AF_INET;
-
- fd = NET_Socket(domain, type, 0);
-
- if (fd == INVALID_SOCKET) {
- NET_ThrowNew(env, WSAGetLastError(), "create");
- return -1;
- }
-
- if (domain == AF_INET6) {
- rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
- sizeof(opt));
- if (rv == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "create");
- closesocket(fd);
- return -1;
- }
- }
-
- return fd;
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: bind0
- * Signature: (ILjava/net/InetAddress;I)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
- (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
- jboolean exclBind)
-{
- SOCKETADDRESS sa;
- int rv, sa_len = 0;
- jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
-
- if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, v4MappedAddress) != 0) {
- return;
- }
-
- rv = NET_WinBind(fd, &sa, sa_len, exclBind);
-
- if (rv == SOCKET_ERROR)
- NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: connect0
- * Signature: (ILjava/net/InetAddress;I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
- (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
- SOCKETADDRESS sa;
- int rv, sa_len = 0;
- jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
-
- if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, v4MappedAddress) != 0) {
- return -1;
- }
-
- rv = connect(fd, &sa.sa, sa_len);
- if (rv == SOCKET_ERROR) {
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK) {
- return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
- } else if (err == WSAEADDRNOTAVAIL) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
- "connect: Address is invalid on local machine,"
- " or port is not valid on remote machine");
- } else {
- NET_ThrowNew(env, err, "connect");
- }
- return -1; // return value not important.
- }
- return rv;
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: waitForConnect
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
- (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
- int rv, retry;
- int optlen = sizeof(rv);
- fd_set wr, ex;
- struct timeval t;
-
- FD_ZERO(&wr);
- FD_ZERO(&ex);
- FD_SET(fd, &wr);
- FD_SET(fd, &ex);
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
-
- /*
- * Wait for timeout, connection established or
- * connection failed.
- */
- rv = select(fd+1, 0, &wr, &ex, &t);
-
- /*
- * Timeout before connection is established/failed so
- * we throw exception and shutdown input/output to prevent
- * socket from being used.
- * The socket should be closed immediately by the caller.
- */
- if (rv == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
- "connect timed out");
- shutdown( fd, SD_BOTH );
- return;
- }
-
- /*
- * Socket is writable or error occurred. On some Windows editions
- * the socket will appear writable when the connect fails so we
- * check for error rather than writable.
- */
- if (!FD_ISSET(fd, &ex)) {
- return; /* connection established */
- }
-
- /*
- * Connection failed. The logic here is designed to work around
- * bug on Windows NT whereby using getsockopt to obtain the
- * last error (SO_ERROR) indicates there is no error. The workaround
- * on NT is to allow winsock to be scheduled and this is done by
- * yielding and retrying. As yielding is problematic in heavy
- * load conditions we attempt up to 3 times to get the error reason.
- */
- for (retry=0; retry<3; retry++) {
- NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
- (char*)&rv, &optlen);
- if (rv) {
- break;
- }
- Sleep(0);
- }
-
- if (rv == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Unable to establish connection");
- } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
- "connect: Address is invalid on local machine,"
- " or port is not valid on remote machine");
- } else {
- NET_ThrowNew(env, rv, "connect");
- }
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: localPort0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_localPort0
- (JNIEnv *env, jclass clazz, jint fd) {
- SOCKETADDRESS sa;
- int len = sizeof(sa);
-
- if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
- if (WSAGetLastError() == WSAENOTSOCK) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Socket closed");
- } else {
- NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
- }
- return -1;
- }
- return (int) ntohs((u_short)GET_PORT(&sa));
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: localAddress
- * Signature: (ILjava/net/InetAddressContainer;)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress
- (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
- int port;
- SOCKETADDRESS sa;
- int len = sizeof(sa);
- jobject iaObj;
- jclass iaContainerClass;
- jfieldID iaFieldID;
-
- if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
- return;
- }
- iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
- CHECK_NULL(iaObj);
-
- iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
- iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
- CHECK_NULL(iaFieldID);
- (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
-}
-
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: listen0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_listen0
- (JNIEnv *env, jclass clazz, jint fd, jint backlog) {
- if (listen(fd, backlog) == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "listen failed");
- }
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: accept0
- * Signature: (I[Ljava/net/InetSocketAddress;)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
- (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
- int newfd, port=0;
- jobject isa;
- jobject ia;
- SOCKETADDRESS sa;
- int len = sizeof(sa);
-
- memset((char *)&sa, 0, len);
- newfd = accept(fd, &sa.sa, &len);
-
- if (newfd == INVALID_SOCKET) {
- NET_ThrowNew(env, WSAGetLastError(), "accept failed");
- return -1;
- }
-
- SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
-
- ia = NET_SockaddrToInetAddress(env, &sa, &port);
- isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
- if (isa == NULL) {
- closesocket(newfd);
- return -1;
- }
- (*env)->SetObjectArrayElement(env, isaa, 0, isa);
-
- return newfd;
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: waitForNewConnection
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForNewConnection
- (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
- int rv;
-
- rv = NET_Timeout(fd, timeout);
- if (rv == 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
- "Accept timed out");
- } else if (rv == -1) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
- } else if (rv == -2) {
- JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
- "operation interrupted");
- }
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: available0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_available0
- (JNIEnv *env, jclass clazz, jint fd) {
- jint available = -1;
-
- if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "socket available");
- }
-
- return available;
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: close0
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_close0
- (JNIEnv *env, jclass clazz, jint fd) {
- NET_SocketClose(fd);
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: shutdown0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_shutdown0
- (JNIEnv *env, jclass clazz, jint fd, jint howto) {
- shutdown(fd, howto);
-}
-
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: setIntOption
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_DualStackPlainSocketImpl_setIntOption
- (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
-{
- int level = 0, opt = 0;
- struct linger linger = {0, 0};
- char *parg;
- int arglen;
-
- if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
- return;
- }
-
- if (opt == java_net_SocketOptions_SO_LINGER) {
- parg = (char *)&linger;
- arglen = sizeof(linger);
- if (value >= 0) {
- linger.l_onoff = 1;
- linger.l_linger = (unsigned short)value;
- } else {
- linger.l_onoff = 0;
- linger.l_linger = 0;
- }
- } else {
- parg = (char *)&value;
- arglen = sizeof(value);
- }
-
- if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
- NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
- }
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: setSoTimeout0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_DualStackPlainSocketImpl_setSoTimeout0
- (JNIEnv *env, jclass clazz, jint fd, jint timeout)
-{
- /*
- * SO_TIMEOUT is the socket option used to specify the timeout
- * for ServerSocket.accept and Socket.getInputStream().read.
- * It does not typically map to a native level socket option.
- * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
- * socket option to specify a receive timeout on the socket. This
- * receive timeout is applicable to Socket only and the socket
- * option should not be set on ServerSocket.
- */
-
- /*
- * SO_RCVTIMEO is only supported on Microsoft's implementation
- * of Windows Sockets so if WSAENOPROTOOPT returned then
- * reset flag and timeout will be implemented using
- * select() -- see SocketInputStream.socketRead.
- */
- if (isRcvTimeoutSupported) {
- /*
- * Disable SO_RCVTIMEO if timeout is <= 5 second.
- */
- if (timeout <= 5000) {
- timeout = 0;
- }
-
- if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
- sizeof(timeout)) < 0) {
- int err = WSAGetLastError();
- if (err == WSAENOPROTOOPT) {
- isRcvTimeoutSupported = JNI_FALSE;
- } else {
- NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
- }
- }
- }
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: getIntOption
- * Signature: (II)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
- (JNIEnv *env, jclass clazz, jint fd, jint cmd)
-{
- int level = 0, opt = 0;
- int result=0;
- struct linger linger = {0, 0};
- char *arg;
- int arglen;
-
- if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
- JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
- return -1;
- }
-
- if (opt == java_net_SocketOptions_SO_LINGER) {
- arg = (char *)&linger;
- arglen = sizeof(linger);
- } else {
- arg = (char *)&result;
- arglen = sizeof(result);
- }
-
- if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
- NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
- return -1;
- }
-
- if (opt == java_net_SocketOptions_SO_LINGER)
- return linger.l_onoff ? linger.l_linger : -1;
- else
- return result;
-}
-
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: sendOOB
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_sendOOB
- (JNIEnv *env, jclass clazz, jint fd, jint data) {
- jint n;
- unsigned char d = (unsigned char) data & 0xff;
-
- n = send(fd, (char *)&data, 1, MSG_OOB);
- if (n == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "send");
- }
-}
-
-/*
- * Class: java_net_DualStackPlainSocketImpl
- * Method: configureBlocking
- * Signature: (IZ)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_configureBlocking
- (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
- u_long arg;
- int result;
-
- if (blocking == JNI_TRUE) {
- arg = SET_BLOCKING; // 0
- } else {
- arg = SET_NONBLOCKING; // 1
- }
-
- result = ioctlsocket(fd, FIONBIO, &arg);
- if (result == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/windows/native/libnet/PlainSocketImpl.c Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include "net_util.h"
+
+#include "java_net_PlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
+
+#define SET_BLOCKING 0
+#define SET_NONBLOCKING 1
+
+static jclass isa_class; /* java.net.InetSocketAddress */
+static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_initIDs
+ (JNIEnv *env, jclass clazz) {
+
+ jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
+ CHECK_NULL(cls);
+ isa_class = (*env)->NewGlobalRef(env, cls);
+ CHECK_NULL(isa_class);
+ isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
+ "(Ljava/net/InetAddress;I)V");
+ CHECK_NULL(isa_ctorID);
+ initInetAddressIDs(env);
+
+ // implement read timeout with select.
+ isRcvTimeoutSupported = JNI_FALSE;
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socket0
+ * Signature: (ZZ)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_socket0
+ (JNIEnv *env, jclass clazz, jboolean stream) {
+ int fd, rv, opt = 0;
+ int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+ int domain = ipv6_available() ? AF_INET6 : AF_INET;
+
+ fd = NET_Socket(domain, type, 0);
+
+ if (fd == INVALID_SOCKET) {
+ NET_ThrowNew(env, WSAGetLastError(), "create");
+ return -1;
+ }
+
+ if (domain == AF_INET6) {
+ rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
+ sizeof(opt));
+ if (rv == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "create");
+ closesocket(fd);
+ return -1;
+ }
+ }
+
+ return fd;
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: bind0
+ * Signature: (ILjava/net/InetAddress;I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_bind0
+ (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
+ jboolean exclBind)
+{
+ SOCKETADDRESS sa;
+ int rv, sa_len = 0;
+ jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
+
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+ &sa_len, v4MappedAddress) != 0) {
+ return;
+ }
+
+ rv = NET_WinBind(fd, &sa, sa_len, exclBind);
+
+ if (rv == SOCKET_ERROR)
+ NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: connect0
+ * Signature: (ILjava/net/InetAddress;I)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_connect0
+ (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
+ SOCKETADDRESS sa;
+ int rv, sa_len = 0;
+ jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
+
+ if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+ &sa_len, v4MappedAddress) != 0) {
+ return -1;
+ }
+
+ rv = connect(fd, &sa.sa, sa_len);
+ if (rv == SOCKET_ERROR) {
+ int err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK) {
+ return java_net_PlainSocketImpl_WOULDBLOCK;
+ } else if (err == WSAEADDRNOTAVAIL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
+ "connect: Address is invalid on local machine,"
+ " or port is not valid on remote machine");
+ } else {
+ NET_ThrowNew(env, err, "connect");
+ }
+ // return value not important.
+ }
+ return rv;
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: waitForConnect
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_waitForConnect
+ (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
+ int rv, retry;
+ int optlen = sizeof(rv);
+ fd_set wr, ex;
+ struct timeval t;
+
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+ FD_SET(fd, &wr);
+ FD_SET(fd, &ex);
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+
+ /*
+ * Wait for timeout, connection established or
+ * connection failed.
+ */
+ rv = select(fd+1, 0, &wr, &ex, &t);
+
+ /*
+ * Timeout before connection is established/failed so
+ * we throw exception and shutdown input/output to prevent
+ * socket from being used.
+ * The socket should be closed immediately by the caller.
+ */
+ if (rv == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "connect timed out");
+ shutdown(fd, SD_BOTH);
+ return;
+ }
+
+ /*
+ * Socket is writable or error occurred. On some Windows editions
+ * the socket will appear writable when the connect fails so we
+ * check for error rather than writable.
+ */
+ if (!FD_ISSET(fd, &ex)) {
+ return; /* connection established */
+ }
+
+ /*
+ * Connection failed. The logic here is designed to work around
+ * bug on Windows NT whereby using getsockopt to obtain the
+ * last error (SO_ERROR) indicates there is no error. The workaround
+ * on NT is to allow winsock to be scheduled and this is done by
+ * yielding and retrying. As yielding is problematic in heavy
+ * load conditions we attempt up to 3 times to get the error reason.
+ */
+ for (retry = 0; retry < 3; retry++) {
+ NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
+ (char*)&rv, &optlen);
+ if (rv) {
+ break;
+ }
+ Sleep(0);
+ }
+
+ if (rv == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Unable to establish connection");
+ } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
+ "connect: Address is invalid on local machine,"
+ " or port is not valid on remote machine");
+ } else {
+ NET_ThrowNew(env, rv, "connect");
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: localPort0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_localPort0
+ (JNIEnv *env, jclass clazz, jint fd) {
+ SOCKETADDRESS sa;
+ int len = sizeof(sa);
+
+ if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
+ if (WSAGetLastError() == WSAENOTSOCK) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ } else {
+ NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
+ }
+ return -1;
+ }
+ return (int) ntohs((u_short)GET_PORT(&sa));
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: localAddress
+ * Signature: (ILjava/net/InetAddressContainer;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_localAddress
+ (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
+ int port;
+ SOCKETADDRESS sa;
+ int len = sizeof(sa);
+ jobject iaObj;
+ jclass iaContainerClass;
+ jfieldID iaFieldID;
+
+ if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
+ return;
+ }
+ iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
+ CHECK_NULL(iaObj);
+
+ iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
+ iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
+ CHECK_NULL(iaFieldID);
+ (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: listen0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_listen0
+ (JNIEnv *env, jclass clazz, jint fd, jint backlog) {
+ if (listen(fd, backlog) == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "listen failed");
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: accept0
+ * Signature: (I[Ljava/net/InetSocketAddress;)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_accept0
+ (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
+ int newfd, port = 0;
+ jobject isa;
+ jobject ia;
+ SOCKETADDRESS sa;
+ int len = sizeof(sa);
+
+ memset((char *)&sa, 0, len);
+ newfd = accept(fd, &sa.sa, &len);
+
+ if (newfd == INVALID_SOCKET) {
+ NET_ThrowNew(env, WSAGetLastError(), "accept failed");
+ return -1;
+ }
+
+ SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
+
+ ia = NET_SockaddrToInetAddress(env, &sa, &port);
+ isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
+ if (isa == NULL) {
+ closesocket(newfd);
+ return -1;
+ }
+ (*env)->SetObjectArrayElement(env, isaa, 0, isa);
+
+ return newfd;
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: waitForNewConnection
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_waitForNewConnection
+ (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
+ int rv;
+
+ rv = NET_Timeout(fd, timeout);
+ if (rv == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Accept timed out");
+ } else if (rv == -1) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
+ } else if (rv == -2) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: available0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_available0
+ (JNIEnv *env, jclass clazz, jint fd) {
+ jint available = -1;
+
+ if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "socket available");
+ }
+
+ return available;
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: close0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_close0
+ (JNIEnv *env, jclass clazz, jint fd) {
+ NET_SocketClose(fd);
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: shutdown0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_shutdown0
+ (JNIEnv *env, jclass clazz, jint fd, jint howto) {
+ shutdown(fd, howto);
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: setIntOption
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_setIntOption
+ (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
+{
+ int level = 0, opt = 0;
+ struct linger linger = {0, 0};
+ char *parg;
+ int arglen;
+
+ if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
+ return;
+ }
+
+ if (opt == java_net_SocketOptions_SO_LINGER) {
+ parg = (char *)&linger;
+ arglen = sizeof(linger);
+ if (value >= 0) {
+ linger.l_onoff = 1;
+ linger.l_linger = (unsigned short)value;
+ } else {
+ linger.l_onoff = 0;
+ linger.l_linger = 0;
+ }
+ } else {
+ parg = (char *)&value;
+ arglen = sizeof(value);
+ }
+
+ if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
+ NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: setSoTimeout0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_setSoTimeout0
+ (JNIEnv *env, jclass clazz, jint fd, jint timeout)
+{
+ /*
+ * SO_TIMEOUT is the socket option used to specify the timeout
+ * for ServerSocket.accept and Socket.getInputStream().read.
+ * It does not typically map to a native level socket option.
+ * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
+ * socket option to specify a receive timeout on the socket. This
+ * receive timeout is applicable to Socket only and the socket
+ * option should not be set on ServerSocket.
+ */
+
+ /*
+ * SO_RCVTIMEO is only supported on Microsoft's implementation
+ * of Windows Sockets so if WSAENOPROTOOPT returned then
+ * reset flag and timeout will be implemented using
+ * select() -- see SocketInputStream.socketRead.
+ */
+ if (isRcvTimeoutSupported) {
+ /*
+ * Disable SO_RCVTIMEO if timeout is <= 5 second.
+ */
+ if (timeout <= 5000) {
+ timeout = 0;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
+ sizeof(timeout)) < 0) {
+ int err = WSAGetLastError();
+ if (err == WSAENOPROTOOPT) {
+ isRcvTimeoutSupported = JNI_FALSE;
+ } else {
+ NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
+ }
+ }
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: getIntOption
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_getIntOption
+ (JNIEnv *env, jclass clazz, jint fd, jint cmd)
+{
+ int level = 0, opt = 0;
+ int result = 0;
+ struct linger linger = {0, 0};
+ char *arg;
+ int arglen;
+
+ if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
+ return -1;
+ }
+
+ if (opt == java_net_SocketOptions_SO_LINGER) {
+ arg = (char *)&linger;
+ arglen = sizeof(linger);
+ } else {
+ arg = (char *)&result;
+ arglen = sizeof(result);
+ }
+
+ if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
+ NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
+ return -1;
+ }
+
+ if (opt == java_net_SocketOptions_SO_LINGER)
+ return linger.l_onoff ? linger.l_linger : -1;
+ else
+ return result;
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: sendOOB
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_sendOOB
+ (JNIEnv *env, jclass clazz, jint fd, jint data) {
+ jint n;
+ unsigned char d = (unsigned char) data & 0xff;
+
+ n = send(fd, (char *)&data, 1, MSG_OOB);
+ if (n == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "send");
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: configureBlocking
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_configureBlocking
+ (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
+ u_long arg;
+ int result;
+
+ if (blocking == JNI_TRUE) {
+ arg = SET_BLOCKING; // 0
+ } else {
+ arg = SET_NONBLOCKING; // 1
+ }
+
+ result = ioctlsocket(fd, FIONBIO, &arg);
+ if (result == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
+ }
+}
--- a/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c Thu Apr 26 17:59:02 2018 +0200
@@ -63,13 +63,6 @@
static jclass ia4_clazz;
static jmethodID ia4_ctor;
-static CRITICAL_SECTION sizeCheckLock;
-
-/* Windows OS version is XP or better */
-static int xp_or_later = 0;
-/* Windows OS version is Windows 2000 or better */
-static int w2k_or_later = 0;
-
/*
* Notes about UDP/IPV6 on Windows (XP and 2003 server):
*
@@ -137,182 +130,6 @@
}
/*
- * This function returns JNI_TRUE if the datagram size exceeds the underlying
- * provider's ability to send to the target address. The following OS
- * oddities have been observed :-
- *
- * 1. On Windows 95/98 if we try to send a datagram > 12k to an application
- * on the same machine then the send will fail silently.
- *
- * 2. On Windows ME if we try to send a datagram > supported by underlying
- * provider then send will not return an error.
- *
- * 3. On Windows NT/2000 if we exceeds the maximum size then send will fail
- * with WSAEADDRNOTAVAIL.
- *
- * 4. On Windows 95/98 if we exceed the maximum size when sending to
- * another machine then WSAEINVAL is returned.
- *
- */
-jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size)
-{
-#define DEFAULT_MSG_SIZE 65527
- static jboolean initDone;
- static jboolean is95or98;
- static int maxmsg;
-
- typedef struct _netaddr { /* Windows 95/98 only */
- unsigned long addr;
- struct _netaddr *next;
- } netaddr;
- static netaddr *addrList;
- netaddr *curr;
-
- /*
- * First time we are called we must determine which OS this is and also
- * get the maximum size supported by the underlying provider.
- *
- * In addition on 95/98 we must enumerate our IP addresses.
- */
- if (!initDone) {
- EnterCriticalSection(&sizeCheckLock);
-
- if (initDone) {
- /* another thread got there first */
- LeaveCriticalSection(&sizeCheckLock);
-
- } else {
- OSVERSIONINFO ver;
- int len;
-
- /*
- * Step 1: Determine which OS this is.
- */
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
-
- is95or98 = JNI_FALSE;
- if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
- ver.dwMajorVersion == 4 &&
- (ver.dwMinorVersion == 0 || ver.dwMinorVersion == 10)) {
-
- is95or98 = JNI_TRUE;
- }
-
- /*
- * Step 2: Determine the maximum datagram supported by the
- * underlying provider. On Windows 95 if winsock hasn't been
- * upgraded (ie: unsupported configuration) then we assume
- * the default 64k limit.
- */
- len = sizeof(maxmsg);
- if (NET_GetSockOpt(fd, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&maxmsg, &len) < 0) {
- maxmsg = DEFAULT_MSG_SIZE;
- }
-
- /*
- * Step 3: On Windows 95/98 then enumerate the IP addresses on
- * this machine. This is neccesary because we need to check if the
- * datagram is being sent to an application on the same machine.
- */
- if (is95or98) {
- char hostname[255];
- struct hostent *hp;
-
- if (gethostname(hostname, sizeof(hostname)) == -1) {
- LeaveCriticalSection(&sizeCheckLock);
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to obtain hostname");
- return JNI_TRUE;
- }
- hp = (struct hostent *)gethostbyname(hostname);
- if (hp != NULL) {
- struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
-
- while (*addrp != (struct in_addr *) 0) {
- curr = (netaddr *)malloc(sizeof(netaddr));
- if (curr == NULL) {
- while (addrList != NULL) {
- curr = addrList->next;
- free(addrList);
- addrList = curr;
- }
- LeaveCriticalSection(&sizeCheckLock);
- JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
- return JNI_TRUE;
- }
- curr->addr = htonl((*addrp)->S_un.S_addr);
- curr->next = addrList;
- addrList = curr;
- addrp++;
- }
- }
- }
-
- /*
- * Step 4: initialization is done so set flag and unlock cs
- */
- initDone = JNI_TRUE;
- LeaveCriticalSection(&sizeCheckLock);
- }
- }
-
- /*
- * Now examine the size of the datagram :-
- *
- * (a) If exceeds size of service provider return 'false' to indicate that
- * we exceed the limit.
- * (b) If not 95/98 then return 'true' to indicate that the size is okay.
- * (c) On 95/98 if the size is <12k we are okay.
- * (d) On 95/98 if size > 12k then check if the destination is the current
- * machine.
- */
- if (size > maxmsg) { /* step (a) */
- return JNI_TRUE;
- }
- if (!is95or98) { /* step (b) */
- return JNI_FALSE;
- }
- if (size <= 12280) { /* step (c) */
- return JNI_FALSE;
- }
-
- /* step (d) */
-
- if ((addr & 0x7f000000) == 0x7f000000) {
- return JNI_TRUE;
- }
- curr = addrList;
- while (curr != NULL) {
- if (curr->addr == addr) {
- return JNI_TRUE;
- }
- curr = curr->next;
- }
- return JNI_FALSE;
-}
-
-/*
- * Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable
- */
-__inline static jboolean supportPortUnreachable() {
- static jboolean initDone;
- static jboolean portUnreachableSupported;
-
- if (!initDone) {
- OSVERSIONINFO ver;
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
- if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT && ver.dwMajorVersion >= 5) {
- portUnreachableSupported = JNI_TRUE;
- } else {
- portUnreachableSupported = JNI_FALSE;
- }
- initDone = JNI_TRUE;
- }
- return portUnreachableSupported;
-}
-
-/*
* This function "purges" all outstanding ICMP port unreachable packets
* outstanding on a socket and returns JNI_TRUE if any ICMP messages
* have been purged. The rational for purging is to emulate normal BSD
@@ -331,13 +148,6 @@
memset((char *)&rmtaddr, 0, sizeof(rmtaddr));
/*
- * A no-op if this OS doesn't support it.
- */
- if (!supportPortUnreachable()) {
- return JNI_FALSE;
- }
-
- /*
* Peek at the queue to see if there is an ICMP port unreachable. If there
* is then receive it.
*/
@@ -370,16 +180,6 @@
*/
JNIEXPORT void JNICALL
Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
-
- OSVERSIONINFO ver;
- int version;
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
-
- version = ver.dwMajorVersion * 10 + ver.dwMinorVersion;
- xp_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 51);
- w2k_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 50);
-
/* get fieldIDs */
pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;");
CHECK_NULL(pdsi_fdID);
@@ -409,9 +209,6 @@
CHECK_NULL(ia4_clazz);
ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "<init>", "()V");
CHECK_NULL(ia4_ctor);
-
-
- InitializeCriticalSection(&sizeCheckLock);
}
JNIEXPORT void JNICALL
@@ -524,6 +321,8 @@
jint fd = -1, fd1 = -1, fdc, family;
SOCKETADDRESS rmtaddr;
int rmtaddrlen = 0;
+ DWORD x1, x2; /* ignored result codes */
+ int res, t;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -553,16 +352,13 @@
fdc = family == java_net_InetAddress_IPv4 ? fd : fd1;
- if (xp_or_later) {
- /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
- * returns connection reset errors on connected UDP sockets (as well
- * as connected sockets). The solution is to only enable this feature
- * when the socket is connected
- */
- DWORD x1, x2; /* ignored result codes */
- int res, t = TRUE;
- res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
- }
+ /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
+ * returns connection reset errors on connected UDP sockets (as well
+ * as connected sockets). The solution is to only enable this feature
+ * when the socket is connected
+ */
+ t = TRUE;
+ res = WSAIoctl(fdc, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr,
&rmtaddrlen, JNI_FALSE) != 0) {
@@ -588,6 +384,8 @@
/* The fdObj'fd */
jint fd, len;
SOCKETADDRESS addr;
+ DWORD x1 = 0, x2 = 0; /* ignored result codes */
+ int t;
if (family == java_net_InetAddress_IPv4) {
fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
@@ -610,11 +408,8 @@
* use SIO_UDP_CONNRESET
* to disable ICMP port unreachable handling here.
*/
- if (xp_or_later) {
- DWORD x1 = 0, x2 = 0; /* ignored result codes */
- int t = FALSE;
- WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
- }
+ t = FALSE;
+ WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
}
/*
@@ -632,7 +427,6 @@
jint fd;
jobject iaObj;
- jint address;
jint family;
jint packetBufferOffset, packetBufferLen, packetPort;
@@ -697,32 +491,6 @@
}
if (packetBufferLen > MAX_BUFFER_LEN) {
-
- /*
- * On 95/98 if we try to send a datagram >12k to an application
- * on the same machine then this will fail silently. Thus we
- * catch this situation here so that we can throw an exception
- * when this arises.
- * On ME if we try to send a datagram with a size greater than
- * that supported by the service provider then no error is
- * returned.
- */
- if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6.
- * Check is not necessary on these OSes */
- if (connected) {
- address = getInetAddress_addr(env, iaObj);
- } else {
- address = ntohl(rmtaddr.sa4.sin_addr.s_addr);
- }
-
- if (exceedSizeLimit(env, fd, address, packetBufferLen)) {
- if (!((*env)->ExceptionOccurred(env))) {
- NET_ThrowNew(env, WSAEMSGSIZE, "Datagram send failed");
- }
- return;
- }
- }
-
/* When JNI-ifying the JDK's IO routines, we turned
* reads and writes of byte arrays of size greater
* than 2048 bytes into several operations of size 2048.
@@ -1282,16 +1050,15 @@
/*
- * If this Windows edition supports ICMP port unreachable and if we
- * are not connected then we need to know if a timeout has been specified
- * and if so we need to pick up the current time. These are required in
- * order to implement the semantics of timeout, viz :-
+ * If we are not connected then we need to know if a timeout has been
+ * specified and if so we need to pick up the current time. These are
+ * required in order to implement the semantics of timeout, viz :-
* timeout set to t1 but ICMP port unreachable arrives in t2 where
* t2 < t1. In this case we must discard the ICMP packets and then
* wait for the next packet up to a maximum of t1 minus t2.
*/
connected = (*env)->GetBooleanField(env, this, pdsi_connected);
- if (supportPortUnreachable() && !connected && timeout &&!ipv6_supported) {
+ if (!connected && timeout && !ipv6_supported) {
prevTime = JVM_CurrentTimeMillis(env, 0);
}
--- a/src/java.base/windows/native/libnet/net_util_md.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/net_util_md.c Thu Apr 26 17:59:02 2018 +0200
@@ -227,73 +227,9 @@
jint reuseport_supported()
{
- /* SO_REUSEPORT is not supported onn Windows */
+ /* SO_REUSEPORT is not supported on Windows */
return JNI_FALSE;
}
-/*
- * Return the default TOS value
- */
-int NET_GetDefaultTOS() {
- static int default_tos = -1;
- OSVERSIONINFO ver;
- HKEY hKey;
- LONG ret;
-
- /*
- * If default ToS already determined then return it
- */
- if (default_tos >= 0) {
- return default_tos;
- }
-
- /*
- * Assume default is "normal service"
- */
- default_tos = 0;
-
- /*
- * Which OS is this?
- */
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
-
- /*
- * If 2000 or greater then no default ToS in registry
- */
- if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- if (ver.dwMajorVersion >= 5) {
- return default_tos;
- }
- }
-
- /*
- * Query the registry to see if a Default ToS has been set.
- * Different registry entry for NT vs 95/98/ME.
- */
- if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\Tcp\\Parameters",
- 0, KEY_READ, (PHKEY)&hKey);
- } else {
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP\\Parameters",
- 0, KEY_READ, (PHKEY)&hKey);
- }
- if (ret == ERROR_SUCCESS) {
- DWORD dwLen;
- DWORD dwDefaultTOS;
- ULONG ulType;
- dwLen = sizeof(dwDefaultTOS);
-
- ret = RegQueryValueEx(hKey, "DefaultTOS", NULL, &ulType,
- (LPBYTE)&dwDefaultTOS, &dwLen);
- RegCloseKey(hKey);
- if (ret == ERROR_SUCCESS) {
- default_tos = (int)dwDefaultTOS;
- }
- }
- return default_tos;
-}
/* call NET_MapSocketOptionV6 for the IPv6 fd only
* and NET_MapSocketOption for the IPv4 fd
@@ -454,10 +390,7 @@
if (WSAGetLastError() == WSAENOPROTOOPT &&
level == IPPROTO_IP && optname == IP_TOS) {
- int *tos;
- tos = (int *)optval;
- *tos = NET_GetDefaultTOS();
-
+ *((int *)optval) = 0;
rv = 0;
}
}
--- a/src/java.base/windows/native/libnet/net_util_md.h Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/net_util_md.h Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -52,11 +52,6 @@
void NET_ThrowCurrent(JNIEnv *env, char *msg);
-/*
- * Return default Type Of Service
- */
-int NET_GetDefaultTOS(void);
-
typedef union {
struct sockaddr sa;
struct sockaddr_in sa4;
--- a/src/java.base/windows/native/libnet/portconfig.c Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <windows.h>
-#include "jni.h"
-#include "net_util.h"
-#include "sun_net_PortConfig.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct portrange {
- int lower;
- int higher;
-};
-
-static int getPortRange(struct portrange *range)
-{
- OSVERSIONINFO ver;
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
-
- /* Check for major version 5 or less = Windows XP/2003 or older */
- if (ver.dwMajorVersion <= 5) {
- LONG ret;
- HKEY hKey;
- range->lower = 1024;
- range->higher = 4999;
-
- /* check registry to see if upper limit was raised */
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
- 0, KEY_READ, (PHKEY)&hKey
- );
- if (ret == ERROR_SUCCESS) {
- DWORD maxuserport;
- ULONG ulType;
- DWORD dwLen = sizeof(maxuserport);
- ret = RegQueryValueEx(hKey, "MaxUserPort", NULL, &ulType,
- (LPBYTE)&maxuserport, &dwLen);
- RegCloseKey(hKey);
- if (ret == ERROR_SUCCESS) {
- range->higher = maxuserport;
- }
- }
- } else {
- /* There doesn't seem to be an API to access this. "MaxUserPort"
- * is affected, but is not sufficient to determine.
- * so we just use the defaults, which are less likely to change
- */
- range->lower = 49152;
- range->higher = 65535;
- }
- return 0;
-}
-
-/*
- * Class: sun_net_PortConfig
- * Method: getLower0
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_sun_net_PortConfig_getLower0
- (JNIEnv *env, jclass clazz)
-{
- struct portrange range;
- getPortRange(&range);
- return range.lower;
-}
-
-/*
- * Class: sun_net_PortConfig
- * Method: getUpper0
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_sun_net_PortConfig_getUpper0
- (JNIEnv *env, jclass clazz)
-{
- struct portrange range;
- getPortRange(&range);
- return range.higher;
-}
-#ifdef __cplusplus
-}
-#endif
--- a/src/java.base/windows/native/libnio/ch/FileChannelImpl.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnio/ch/FileChannelImpl.c Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -141,31 +141,6 @@
}
JNIEXPORT jlong JNICALL
-Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this,
- jobject fdo, jlong offset)
-{
- BOOL result = 0;
- HANDLE h = (HANDLE)(handleval(env, fdo));
- LARGE_INTEGER where;
- DWORD whence;
-
- if (offset < 0) {
- where.QuadPart = 0;
- whence = FILE_CURRENT;
- } else {
- where.QuadPart = offset;
- whence = FILE_BEGIN;
- }
-
- result = SetFilePointerEx(h, where, &where, whence);
- if (result == 0) {
- JNU_ThrowIOExceptionWithLastError(env, "Seek failed");
- return IOS_THROWN;
- }
- return (jlong)where.QuadPart;
-}
-
-JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
jobject srcFD,
jlong position, jlong count,
@@ -173,14 +148,17 @@
{
const int PACKET_SIZE = 524288;
+ LARGE_INTEGER where;
HANDLE src = (HANDLE)(handleval(env, srcFD));
SOCKET dst = (SOCKET)(fdval(env, dstFD));
DWORD chunkSize = (count > java_lang_Integer_MAX_VALUE) ?
java_lang_Integer_MAX_VALUE : (DWORD)count;
- BOOL result = 0;
+ BOOL result;
- jlong pos = Java_sun_nio_ch_FileChannelImpl_position0(env, this, srcFD, position);
- if (pos == IOS_THROWN) {
+ where.QuadPart = position;
+ result = SetFilePointerEx(src, where, &where, FILE_BEGIN);
+ if (result == 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed");
return IOS_THROWN;
}
--- a/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -298,6 +298,31 @@
return convertReturnVal(env, (jint)written, JNI_FALSE);
}
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_seek0(JNIEnv *env, jclass clazz,
+ jobject fdo, jlong offset)
+{
+ BOOL result = 0;
+ HANDLE h = (HANDLE)(handleval(env, fdo));
+ LARGE_INTEGER where;
+ DWORD whence;
+
+ if (offset < 0) {
+ where.QuadPart = 0;
+ whence = FILE_CURRENT;
+ } else {
+ where.QuadPart = offset;
+ whence = FILE_BEGIN;
+ }
+
+ result = SetFilePointerEx(h, where, &where, whence);
+ if (result == 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed");
+ return IOS_THROWN;
+ }
+ return (jlong)where.QuadPart;
+}
+
JNIEXPORT jint JNICALL
Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this,
jobject fdo, jboolean md)
--- a/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -47,6 +47,7 @@
import java.lang.reflect.UndeclaredThrowableException;
import java.security.PrivilegedAction;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -162,6 +163,16 @@
return LoggingMXBeanAccess.isAvailable();
}
+ /**
+ * Returns an array of the name of all memory pools. The order of the memory pools is
+ * significant and maintained in the VM.
+ */
+ public static String[] getAllMemoryPoolNames() {
+ return Arrays.stream(MemoryImpl.getMemoryPools())
+ .map(MemoryPoolMXBean::getName)
+ .toArray(String[]::new);
+ }
+
// The LoggingMXBeanAccess class uses reflection to determine
// whether java.util.logging is present, and load the actual LoggingMXBean
// implementation.
--- a/src/java.scripting/share/classes/javax/script/AbstractScriptEngine.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.scripting/share/classes/javax/script/AbstractScriptEngine.java Thu Apr 26 17:59:02 2018 +0200
@@ -287,7 +287,7 @@
*/
protected ScriptContext getScriptContext(Bindings nn) {
- SimpleScriptContext ctxt = new SimpleScriptContext();
+ SimpleScriptContext ctxt = new SimpleScriptContext(context.getReader(), context.getWriter(), context.getErrorWriter());
Bindings gs = getBindings(ScriptContext.GLOBAL_SCOPE);
if (gs != null) {
@@ -301,10 +301,6 @@
throw new NullPointerException("Engine scope Bindings may not be null.");
}
- ctxt.setReader(context.getReader());
- ctxt.setWriter(context.getWriter());
- ctxt.setErrorWriter(context.getErrorWriter());
-
return ctxt;
}
--- a/src/java.scripting/share/classes/javax/script/CompiledScript.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.scripting/share/classes/javax/script/CompiledScript.java Thu Apr 26 17:59:02 2018 +0200
@@ -79,13 +79,10 @@
ScriptContext ctxt = getEngine().getContext();
if (bindings != null) {
- SimpleScriptContext tempctxt = new SimpleScriptContext();
+ SimpleScriptContext tempctxt = new SimpleScriptContext(ctxt.getReader(), ctxt.getWriter(), ctxt.getErrorWriter());
tempctxt.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
tempctxt.setBindings(ctxt.getBindings(ScriptContext.GLOBAL_SCOPE),
ScriptContext.GLOBAL_SCOPE);
- tempctxt.setWriter(ctxt.getWriter());
- tempctxt.setReader(ctxt.getReader());
- tempctxt.setErrorWriter(ctxt.getErrorWriter());
ctxt = tempctxt;
}
--- a/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java Thu Apr 26 17:59:02 2018 +0200
@@ -86,11 +86,25 @@
* Create a {@code SimpleScriptContext}.
*/
public SimpleScriptContext() {
+ this(new InputStreamReader(System.in),
+ new PrintWriter(System.out , true),
+ new PrintWriter(System.err, true));
engineScope = new SimpleBindings();
globalScope = null;
- reader = new InputStreamReader(System.in);
- writer = new PrintWriter(System.out , true);
- errorWriter = new PrintWriter(System.err, true);
+ }
+
+ /**
+ * Package-private constructor to avoid needless creation of reader and writers.
+ * It is the caller's responsability to initialize the engine scope.
+ *
+ * @param reader the reader
+ * @param writer the writer
+ * @param errorWriter the error writer
+ */
+ SimpleScriptContext(Reader reader, Writer writer, Writer errorWriter) {
+ this.reader = reader;
+ this.writer = writer;
+ this.errorWriter = errorWriter;
}
/**
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/SchemaContentHandler.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/SchemaContentHandler.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,7 @@
import com.sun.org.apache.xerces.internal.util.SAXLocatorWrapper;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
+import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
import com.sun.org.apache.xerces.internal.util.XMLSymbols;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.QName;
@@ -78,6 +79,7 @@
private final QName fAttributeQName = new QName();
private final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
private final XMLString fTempString = new XMLString();
+ private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
/**
* <p>Constructs an SchemaContentHandler.</p>
@@ -103,6 +105,7 @@
*/
public void startDocument() throws SAXException {
fNeedPushNSContext = true;
+ fNamespaceContext.reset();
try {
fSchemaDOMParser.startDocument(fSAXLocatorWrapper, null, fNamespaceContext, null);
}
@@ -326,7 +329,11 @@
if (nsPrefix.length() > 0) {
prefix = XMLSymbols.PREFIX_XMLNS;
localpart = nsPrefix;
- rawname = fSymbolTable.addSymbol(prefix + ":" + localpart);
+ fStringBuffer.clear();
+ fStringBuffer.append(prefix);
+ fStringBuffer.append(':');
+ fStringBuffer.append(localpart);
+ rawname = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
}
else {
prefix = XMLSymbols.EMPTY_STRING;
@@ -334,7 +341,8 @@
rawname = XMLSymbols.PREFIX_XMLNS;
}
fAttributeQName.setValues(prefix, localpart, rawname, NamespaceContext.XMLNS_URI);
- fAttributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, nsURI);
+ fAttributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol,
+ (nsURI != null) ? nsURI : XMLSymbols.EMPTY_STRING);
}
}
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java Thu Apr 26 17:59:02 2018 +0200
@@ -2266,6 +2266,8 @@
fSecurityManager.isSecureProcessing());
try {
+ parser.setFeature(NAMESPACE_PREFIXES, true);
+ namespacePrefixes = true;
// If this is a Xerces SAX parser set the security manager if there is one
if (parser instanceof SAXParser) {
if (fSecurityManager != null) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,11 +30,11 @@
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.GraalCompilerOptions;
import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.Management;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.debug.DebugContext.Activation;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -52,8 +52,6 @@
private static final AtomicInteger ids = new AtomicInteger();
- private static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
-
private final Main main;
private OptionValues graalOptions;
@@ -99,7 +97,7 @@
final long threadId = Thread.currentThread().getId();
- final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed();
+ final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed() && GraalServices.isThreadAllocatedMemorySupported();
if (printCompilation) {
TTY.println(getMethodDescription() + "...");
}
@@ -108,7 +106,7 @@
final long allocatedBytesBefore;
if (printCompilation) {
start = System.currentTimeMillis();
- allocatedBytesBefore = printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
+ allocatedBytesBefore = GraalServices.getThreadAllocatedBytes(threadId);
} else {
start = 0L;
allocatedBytesBefore = 0L;
@@ -125,7 +123,7 @@
if (printCompilation) {
final long stop = System.currentTimeMillis();
final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1;
- final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId);
+ final long allocatedBytesAfter = GraalServices.getThreadAllocatedBytes(threadId);
final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes));
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java Thu Apr 26 17:59:02 2018 +0200
@@ -45,7 +45,7 @@
import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions;
import org.graalvm.compiler.hotspot.word.MetaspacePointer;
import org.graalvm.compiler.replacements.Snippets;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.WordBase;
final class GraalFilters {
private List<ResolvedJavaType> specialClasses;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Thu Apr 26 17:59:02 2018 +0200
@@ -141,7 +141,7 @@
graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
}
graalOptions = new OptionValues(graalOptions, GeneratePIC, true, ImmutableCode, true);
- GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
+ GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler("JAOTC", JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,7 @@
import com.sun.tools.javac.code.Type.JCVoidType;
import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.code.Type.UnknownType;
+import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
@@ -247,6 +248,26 @@
*/
private final Map<Name, ModuleSymbol> modules = new LinkedHashMap<>();
+ private final Map<Types.UniqueType, VarSymbol> classFields = new HashMap<>();
+
+ public VarSymbol getClassField(Type type, Types types) {
+ return classFields.computeIfAbsent(
+ new UniqueType(type, types), k -> {
+ Type arg = null;
+ if (type.getTag() == ARRAY || type.getTag() == CLASS)
+ arg = types.erasure(type);
+ else if (type.isPrimitiveOrVoid())
+ arg = types.boxedClass(type).type;
+ else
+ throw new AssertionError(type);
+
+ Type t = new ClassType(
+ classType.getEnclosingType(), List.of(arg), classType.tsym);
+ return new VarSymbol(
+ STATIC | PUBLIC | FINAL, names._class, t, type.tsym);
+ });
+ }
+
public void initType(Type type, ClassSymbol c) {
type.tsym = c;
typeOfTag[type.getTag().ordinal()] = type;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Apr 26 17:59:02 2018 +0200
@@ -3731,11 +3731,7 @@
} else if (name == names._class) {
// In this case, we have already made sure in
// visitSelect that qualifier expression is a type.
- Type t = syms.classType;
- List<Type> typeargs = List.of(types.erasure(site));
- t = new ClassType(t.getEnclosingType(), typeargs, t.tsym);
- return new VarSymbol(
- STATIC | PUBLIC | FINAL, names._class, t, site.tsym);
+ return syms.getClassField(site, types);
} else {
// We are seeing a plain identifier as selector.
Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind);
@@ -3773,11 +3769,7 @@
if (name == names._class) {
// In this case, we have already made sure in Select that
// qualifier expression is a type.
- Type t = syms.classType;
- Type arg = types.boxedClass(site).type;
- t = new ClassType(t.getEnclosingType(), List.of(arg), t.tsym);
- return new VarSymbol(
- STATIC | PUBLIC | FINAL, names._class, t, site.tsym);
+ return syms.getClassField(site, types);
} else {
log.error(pos, Errors.CantDeref(site));
return syms.errSymbol;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.GraphUtils.DottableNode;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.Fragment;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Type.*;
@@ -115,7 +116,6 @@
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
log = Log.instance(context);
- inferenceException = new InferenceException(diags);
Options options = Options.instance(context);
Source source = Source.instance(context);
allowGraphInference = Feature.GRAPH_INFERENCE.allowedInSource(source)
@@ -138,33 +138,23 @@
List<JCDiagnostic> messages = List.nil();
- InferenceException(JCDiagnostic.Factory diags) {
- super(diags);
- }
-
- @Override
- InapplicableMethodException setMessage() {
- //no message to set
- return this;
- }
-
- @Override
- InapplicableMethodException setMessage(JCDiagnostic diag) {
- messages = messages.append(diag);
- return this;
+ InferenceException() {
+ super(null);
}
@Override
public JCDiagnostic getDiagnostic() {
return messages.head;
}
-
- void clear() {
- messages = List.nil();
- }
}
- protected final InferenceException inferenceException;
+ InferenceException error(JCDiagnostic diag) {
+ InferenceException result = new InferenceException();
+ if (diag != null) {
+ result.messages = result.messages.append(diag);
+ }
+ return result;
+ }
// <editor-fold defaultstate="collapsed" desc="Inference routines">
/**
@@ -183,7 +173,6 @@
Warner warn) throws InferenceException {
//-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
final InferenceContext inferenceContext = new InferenceContext(this, tvars); //B0
- inferenceException.clear();
try {
DeferredAttr.DeferredAttrContext deferredAttrContext =
resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
@@ -315,7 +304,6 @@
*/
Type check(Attr.ResultInfo resultInfo) {
Warner noWarnings = new Warner(null);
- inferenceException.clear();
List<Type> saved_undet = null;
try {
/** we need to save the inference context before generating target type constraints.
@@ -430,9 +418,7 @@
if (!resultInfo.checkContext.compatible(qtype, rsInfoInfContext.asUndetVar(to), retWarn) ||
//unchecked conversion is not allowed in source 7 mode
(!allowGraphInference && retWarn.hasLint(Lint.LintCategory.UNCHECKED))) {
- throw inferenceException
- .setMessage("infer.no.conforming.instance.exists",
- inferenceContext.restvars(), mt.getReturnType(), to);
+ throw error(diags.fragment(Fragments.InferNoConformingInstanceExists(inferenceContext.restvars(), mt.getReturnType(), to)));
}
return from;
}
@@ -1269,41 +1255,49 @@
* Incorporation error: mismatch between inferred type and given bound.
*/
void reportInstError(UndetVar uv, InferenceBound ib) {
- reportInferenceError(
- String.format("inferred.do.not.conform.to.%s.bounds", StringUtils.toLowerCase(ib.name())),
- uv.getInst(),
- uv.getBounds(ib));
+ switch (ib) {
+ case EQ:
+ throw error(diags.fragment(Fragments.InferredDoNotConformToEqBounds(uv.getInst(), uv.getBounds(ib))));
+ case LOWER:
+ throw error(diags.fragment(Fragments.InferredDoNotConformToLowerBounds(uv.getInst(), uv.getBounds(ib))));
+ case UPPER:
+ throw error(diags.fragment(Fragments.InferredDoNotConformToUpperBounds(uv.getInst(), uv.getBounds(ib))));
+ }
}
/**
* Incorporation error: mismatch between two (or more) bounds of same kind.
*/
void reportBoundError(UndetVar uv, InferenceBound ib) {
- reportInferenceError(
- String.format("incompatible.%s.bounds", StringUtils.toLowerCase(ib.name())),
- uv.qtype,
- uv.getBounds(ib));
+ switch (ib) {
+ case EQ:
+ throw error(diags.fragment(Fragments.IncompatibleEqBounds(uv.qtype, uv.getBounds(ib))));
+ case UPPER:
+ throw error(diags.fragment(Fragments.IncompatibleUpperBounds(uv.qtype, uv.getBounds(ib))));
+ case LOWER:
+ throw new AssertionError("this case shouldn't happen");
+ }
}
/**
* Incorporation error: mismatch between two (or more) bounds of different kinds.
*/
void reportBoundError(UndetVar uv, InferenceBound ib1, InferenceBound ib2) {
- reportInferenceError(
- String.format("incompatible.%s.%s.bounds",
- StringUtils.toLowerCase(ib1.name()),
- StringUtils.toLowerCase(ib2.name())),
+ throw error(diags.fragment(Fragments.IncompatibleBounds(
uv.qtype,
- uv.getBounds(ib1),
- uv.getBounds(ib2));
+ getBoundFragment(ib1, uv.getBounds(ib1)),
+ getBoundFragment(ib2, uv.getBounds(ib2)))));
}
- /**
- * Helper method: reports an inference error.
- */
- void reportInferenceError(String key, Object... args) {
- throw inferenceException.setMessage(key, args);
+ Fragment getBoundFragment(InferenceBound ib, List<Type> types) {
+ switch (ib) {
+ case EQ: return Fragments.EqBounds(types);
+ case LOWER: return Fragments.LowerBounds(types);
+ case UPPER: return Fragments.UpperBounds(types);
+ }
+ throw new AssertionError("can't get to this place");
}
+
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Inference engine">
@@ -1456,9 +1450,7 @@
//note: lobounds should have at least one element
Type owntype = lobounds.tail.tail == null ? lobounds.head : infer.types.lub(lobounds);
if (owntype.isPrimitive() || owntype.hasTag(ERROR)) {
- throw infer.inferenceException
- .setMessage("no.unique.minimal.instance.exists",
- uv.qtype, lobounds);
+ throw infer.error(infer.diags.fragment(Fragments.NoUniqueMinimalInstanceExists(uv.qtype, lobounds)));
} else {
return owntype;
}
@@ -1499,9 +1491,7 @@
//note: hibounds should have at least one element
Type owntype = hibounds.tail.tail == null ? hibounds.head : infer.types.glb(hibounds);
if (owntype.isPrimitive() || owntype.hasTag(ERROR)) {
- throw infer.inferenceException
- .setMessage("no.unique.maximal.instance.exists",
- uv.qtype, hibounds);
+ throw infer.error(infer.diags.fragment(Fragments.NoUniqueMaximalInstanceExists(uv.qtype, hibounds)));
} else {
return owntype;
}
@@ -1677,7 +1667,7 @@
}
}
//no progress
- throw inferenceException.setMessage();
+ throw error(null);
}
}
catch (InferenceException ex) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
-import com.sun.tools.javac.comp.Infer.FreeTypeListener;
import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template;
import com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind;
@@ -60,7 +59,6 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
-import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
@@ -71,6 +69,8 @@
import javax.lang.model.element.ElementVisitor;
+import com.sun.tools.javac.comp.Infer.InferenceException;
+
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.BLOCK;
import static com.sun.tools.javac.code.Flags.STATIC;
@@ -143,9 +143,6 @@
checkVarargsAccessAfterResolution =
Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source);
polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
-
- inapplicableMethodException = new InapplicableMethodException(diags);
-
allowModules = Feature.MODULES.allowedInSource(source);
}
@@ -575,7 +572,7 @@
ForAll pmt = (ForAll) mt;
if (typeargtypes.length() != pmt.tvars.length())
// not enough args
- throw inapplicableMethodException.setMessage("wrong.number.type.args", Integer.toString(pmt.tvars.length()));
+ throw new InapplicableMethodException(diags.fragment(Fragments.WrongNumberTypeArgs(Integer.toString(pmt.tvars.length()))));
// Check type arguments are within bounds
List<Type> formals = pmt.tvars;
List<Type> actuals = typeargtypes;
@@ -583,8 +580,9 @@
List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head),
pmt.tvars, typeargtypes);
for (; bounds.nonEmpty(); bounds = bounds.tail) {
- if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn))
- throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds);
+ if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn)) {
+ throw new InapplicableMethodException(diags.fragment(Fragments.ExplicitParamDoNotConformToBounds(actuals.head, bounds)));
+ }
}
formals = formals.tail;
actuals = actuals.tail;
@@ -811,8 +809,6 @@
protected void reportMC(DiagnosticPosition pos, MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
boolean inferDiag = inferenceContext != infer.emptyContext;
- InapplicableMethodException ex = inferDiag ?
- infer.inferenceException : inapplicableMethodException;
if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
Object[] args2 = new Object[args.length + 1];
System.arraycopy(args, 0, args2, 1, args.length);
@@ -820,7 +816,9 @@
args = args2;
}
String key = inferDiag ? diag.inferKey : diag.basicKey;
- throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
+ throw inferDiag ?
+ infer.error(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args)) :
+ new InapplicableMethodException(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
}
public MethodCheck mostSpecificCheck(List<Type> actuals) {
@@ -1006,7 +1004,7 @@
}
public void report(DiagnosticPosition pos, JCDiagnostic details) {
- throw inapplicableMethodException.setMessage(details);
+ throw new InapplicableMethodException(details);
}
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
@@ -1367,31 +1365,15 @@
private static final long serialVersionUID = 0;
JCDiagnostic diagnostic;
- JCDiagnostic.Factory diags;
-
- InapplicableMethodException(JCDiagnostic.Factory diags) {
- this.diagnostic = null;
- this.diags = diags;
- }
- InapplicableMethodException setMessage() {
- return setMessage((JCDiagnostic)null);
- }
- InapplicableMethodException setMessage(String key) {
- return setMessage(key != null ? diags.fragment(key) : null);
- }
- InapplicableMethodException setMessage(String key, Object... args) {
- return setMessage(key != null ? diags.fragment(key, args) : null);
- }
- InapplicableMethodException setMessage(JCDiagnostic diag) {
+
+ InapplicableMethodException(JCDiagnostic diag) {
this.diagnostic = diag;
- return this;
}
public JCDiagnostic getDiagnostic() {
return diagnostic;
}
}
- private final InapplicableMethodException inapplicableMethodException;
/* ***************************************************************************
* Symbol lookup
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Apr 26 17:59:02 2018 +0200
@@ -2302,6 +2302,7 @@
compiler.misc.no.unique.maximal.instance.exists=\
no unique maximal instance exists for type variable {0} with upper bounds {1}
+# 0: type, 1: list of type
compiler.misc.no.unique.minimal.instance.exists=\
no unique minimal instance exists for type variable {0} with lower bounds {1}
@@ -2313,23 +2314,23 @@
compiler.misc.incompatible.eq.bounds=\
inference variable {0} has incompatible equality constraints {1}
-# 0: type, 1: list of type, 2: list of type
-compiler.misc.incompatible.eq.upper.bounds=\
- inference variable {0} has incompatible bounds\n\
- equality constraints: {1}\n\
- upper bounds: {2}
-
-# 0: type, 1: list of type, 2: list of type
-compiler.misc.incompatible.upper.lower.bounds=\
+# 0: type, 1: fragment, 2: fragment
+compiler.misc.incompatible.bounds=\
inference variable {0} has incompatible bounds\n\
- upper bounds: {1}\n\
- lower bounds: {2}
-
-# 0: type, 1: list of type, 2: list of type
-compiler.misc.incompatible.eq.lower.bounds=\
- inference variable {0} has incompatible bounds\n\
- equality constraints: {1}\n\
- lower bounds: {2}
+ {1}\n\
+ {2}
+
+# 0: list of type
+compiler.misc.lower.bounds=\
+ lower bounds: {0}
+
+# 0: list of type
+compiler.misc.eq.bounds=\
+ equality constraints: {0}
+
+# 0: list of type
+compiler.misc.upper.bounds=\
+ lower bounds: {0}
# 0: list of type, 1: type, 2: type
compiler.misc.infer.no.conforming.instance.exists=\
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c Thu Apr 26 17:59:02 2018 +0200
@@ -212,29 +212,51 @@
// mapped. This structure gets written to a file. It is not a class,
// so that the compilers don't add any compiler-private data to it.
-#define NUM_SHARED_MAPS 4
+#define NUM_SHARED_MAPS 9
// Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 1
+#define CURRENT_ARCHIVE_VERSION 3
+
+typedef unsigned char* address;
+typedef uintptr_t uintx;
+typedef intptr_t intx;
struct FileMapHeader {
- int _magic; // identify file type.
- int _version; // (from enum, above.)
- size_t _alignment; // how shared archive should be aligned
+ int _magic; // identify file type.
+ int _crc; // header crc checksum.
+ int _version; // (from enum, above.)
+ size_t _alignment; // how shared archive should be aligned
+ int _obj_alignment; // value of ObjectAlignmentInBytes
+ address _narrow_oop_base; // compressed oop encoding base
+ int _narrow_oop_shift; // compressed oop encoding shift
+ bool _compact_strings; // value of CompactStrings
+ uintx _max_heap_size; // java max heap size during dumping
+ int _narrow_oop_mode; // compressed oop encoding mode
+ int _narrow_klass_shift; // save narrow klass base and shift
+ address _narrow_klass_base;
+ char* _misc_data_patching_start;
+ char* _read_only_tables_start;
+ address _cds_i2i_entry_code_buffers;
+ size_t _cds_i2i_entry_code_buffers_size;
+ size_t _core_spaces_size; // number of bytes allocated by the core spaces
+ // (mc, md, ro, rw and od).
+
struct space_info {
- int _file_offset; // sizeof(this) rounded to vm page size
- char* _base; // copy-on-write base address
- size_t _capacity; // for validity checking
- size_t _used; // for setting space top on read
-
+ int _crc; // crc checksum of the current space
+ size_t _file_offset; // sizeof(this) rounded to vm page size
+ union {
+ char* _base; // copy-on-write base address
+ intx _offset; // offset from the compressed oop encoding base, only used
+ // by archive heap space
+ } _addr;
+ size_t _used; // for setting space top on read
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
// the C type matching the C++ bool type on any given platform.
// We assume the corresponding C type is char but licensees
// may need to adjust the type of these fields.
- char _read_only; // read only space?
- char _allow_exec; // executable code in space?
-
+ char _read_only; // read only space?
+ char _allow_exec; // executable code in space?
} _space[NUM_SHARED_MAPS];
// Ignore the rest of the FileMapHeader. We don't need those fields here.
@@ -381,7 +403,7 @@
// add read-only maps from classes.jsa to the list of maps
for (m = 0; m < NUM_SHARED_MAPS; m++) {
if (header._space[m]._read_only) {
- base = (uintptr_t) header._space[m]._base;
+ base = (uintptr_t) header._space[m]._addr._base;
// no need to worry about the fractional pages at-the-end.
// possible fractional pages are handled by core_read_data.
add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
--- a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -213,29 +213,52 @@
// mapped. This structure gets written to a file. It is not a class,
// so that the compilers don't add any compiler-private data to it.
-#define NUM_SHARED_MAPS 4
+#define NUM_SHARED_MAPS 9
// Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 1
+#define CURRENT_ARCHIVE_VERSION 3
+
+typedef unsigned char* address;
+typedef uintptr_t uintx;
+typedef intptr_t intx;
+
struct FileMapHeader {
- int _magic; // identify file type.
- int _version; // (from enum, above.)
- size_t _alignment; // how shared archive should be aligned
+ int _magic; // identify file type.
+ int _crc; // header crc checksum.
+ int _version; // (from enum, above.)
+ size_t _alignment; // how shared archive should be aligned
+ int _obj_alignment; // value of ObjectAlignmentInBytes
+ address _narrow_oop_base; // compressed oop encoding base
+ int _narrow_oop_shift; // compressed oop encoding shift
+ bool _compact_strings; // value of CompactStrings
+ uintx _max_heap_size; // java max heap size during dumping
+ int _narrow_oop_mode; // compressed oop encoding mode
+ int _narrow_klass_shift; // save narrow klass base and shift
+ address _narrow_klass_base;
+ char* _misc_data_patching_start;
+ char* _read_only_tables_start;
+ address _cds_i2i_entry_code_buffers;
+ size_t _cds_i2i_entry_code_buffers_size;
+ size_t _core_spaces_size; // number of bytes allocated by the core spaces
+ // (mc, md, ro, rw and od).
+
struct space_info {
- int _file_offset; // sizeof(this) rounded to vm page size
- char* _base; // copy-on-write base address
- size_t _capacity; // for validity checking
- size_t _used; // for setting space top on read
-
+ int _crc; // crc checksum of the current space
+ size_t _file_offset; // sizeof(this) rounded to vm page size
+ union {
+ char* _base; // copy-on-write base address
+ intx _offset; // offset from the compressed oop encoding base, only used
+ // by archive heap space
+ } _addr;
+ size_t _used; // for setting space top on read
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
// the C type matching the C++ bool type on any given platform.
// We assume the corresponding C type is char but licensees
// may need to adjust the type of these fields.
- char _read_only; // read only space?
- char _allow_exec; // executable code in space?
-
+ char _read_only; // read only space?
+ char _allow_exec; // executable code in space?
} _space[NUM_SHARED_MAPS];
// Ignore the rest of the FileMapHeader. We don't need those fields here.
@@ -282,15 +305,14 @@
return true;
}
+// mangled name of Arguments::SharedArchivePath
+#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
+
#ifdef __APPLE__
#define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
-// mangled name of Arguments::SharedArchivePath
-#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
#define LIBJVM_NAME "/libjvm.dylib"
#else
#define USE_SHARED_SPACES_SYM "UseSharedSpaces"
-// mangled name of Arguments::SharedArchivePath
-#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
#define LIBJVM_NAME "/libjvm.so"
#endif // __APPLE_
@@ -387,7 +409,7 @@
// add read-only maps from classes.jsa to the list of maps
for (m = 0; m < NUM_SHARED_MAPS; m++) {
if (header._space[m]._read_only) {
- base = (uintptr_t) header._space[m]._base;
+ base = (uintptr_t) header._space[m]._addr._base;
// no need to worry about the fractional pages at-the-end.
// possible fractional pages are handled by core_read_data.
add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.memory;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.VMObject;
+import sun.jvm.hotspot.runtime.VMObjectFactory;
+import sun.jvm.hotspot.types.*;
+
+public class FileMapInfo {
+ private static FileMapHeader header;
+ private static Address headerValue;
+
+ // Fields for class FileMapHeader
+ private static Address mdSpaceValue;
+ private static Address mdRegionBaseAddress;
+ private static Address mdRegionEndAddress;
+
+ // HashMap created by mapping the vTable addresses in the md region with
+ // the corresponding metadata type.
+ private static Map<Address, Type> vTableTypeMap;
+
+ private static Type metadataTypeArray[];
+
+ static {
+ VM.registerVMInitializedObserver(new Observer() {
+ public void update(Observable o, Object data) {
+ initialize(VM.getVM().getTypeDataBase());
+ }
+ });
+ }
+
+ private static void initialize(TypeDataBase db) {
+ // FileMapInfo
+ Type type = db.lookupType("FileMapInfo");
+ AddressField currentInfoField = type.getAddressField("_current_info");
+ long headerFieldOffset = type.getField("_header").getOffset();
+ Address headerAddress = currentInfoField.getValue().addOffsetTo(headerFieldOffset);
+ headerValue = headerAddress.getAddressAt(0);
+
+ // FileMapHeader
+ type = db.lookupType("FileMapInfo::FileMapHeader");
+ AddressField spaceField = type.getAddressField("_space[0]");
+ Address spaceValue = headerValue.addOffsetTo(type.getField("_space[0]").getOffset());
+ mdSpaceValue = spaceValue.addOffsetTo(3 * spaceField.getSize());
+
+ // SpaceInfo
+ type = db.lookupType("FileMapInfo::FileMapHeader::space_info");
+ long mdRegionBaseAddressOffset = type.getField("_addr._base").getOffset();
+ mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
+ long mdRegionSizeOffset = type.getField("_used").getOffset();
+ long mdRegionSize = (mdSpaceValue.addOffsetTo(mdRegionSizeOffset)).getAddressAt(0).asLongValue();
+ mdRegionEndAddress = mdRegionBaseAddress.addOffsetTo(mdRegionSize);
+
+ populateMetadataTypeArray(db);
+ }
+
+ private static void populateMetadataTypeArray(TypeDataBase db) {
+ metadataTypeArray = new Type[8];
+
+ metadataTypeArray[0] = db.lookupType("ConstantPool");
+ metadataTypeArray[1] = db.lookupType("InstanceKlass");
+ metadataTypeArray[2] = db.lookupType("InstanceClassLoaderKlass");
+ metadataTypeArray[3] = db.lookupType("InstanceMirrorKlass");
+ metadataTypeArray[4] = db.lookupType("InstanceRefKlass");
+ metadataTypeArray[5] = db.lookupType("Method");
+ metadataTypeArray[6] = db.lookupType("ObjArrayKlass");
+ metadataTypeArray[7] = db.lookupType("TypeArrayKlass");
+ }
+
+ public FileMapHeader getHeader() {
+ if (header == null) {
+ header = (FileMapHeader) VMObjectFactory.newObject(FileMapInfo.FileMapHeader.class, headerValue);
+ }
+ return header;
+ }
+
+ public boolean inCopiedVtableSpace(Address vptrAddress) {
+ FileMapHeader fmHeader = getHeader();
+ return fmHeader.inCopiedVtableSpace(vptrAddress);
+ }
+
+ public Type getTypeForVptrAddress(Address vptrAddress) {
+ if (vTableTypeMap == null) {
+ getHeader().createVtableTypeMapping();
+ }
+ return vTableTypeMap.get(vptrAddress);
+ }
+
+
+ //------------------------------------------------------------------------------------------
+
+ public static class FileMapHeader extends VMObject {
+
+ public FileMapHeader(Address addr) {
+ super(addr);
+ }
+
+ public boolean inCopiedVtableSpace(Address vptrAddress) {
+ if (vptrAddress.greaterThan(mdRegionBaseAddress) &&
+ vptrAddress.lessThanOrEqual(mdRegionEndAddress)) {
+ return true;
+ }
+ return false;
+ }
+
+ public void createVtableTypeMapping() {
+ vTableTypeMap = new HashMap<Address, Type>();
+ long metadataVTableSize = 0;
+ long addressSize = VM.getVM().getAddressSize();
+
+ Address copiedVtableAddress = mdRegionBaseAddress;
+ for (int i=0; i < metadataTypeArray.length; i++) {
+ // The first entry denotes the vtable size.
+ metadataVTableSize = copiedVtableAddress.getAddressAt(0).asLongValue();
+ vTableTypeMap.put(copiedVtableAddress.addOffsetTo(addressSize), metadataTypeArray[i]);
+
+ // The '+ 1' below is to skip the entry containing the size of this metadata's vtable.
+ copiedVtableAddress =
+ copiedVtableAddress.addOffsetTo((metadataVTableSize + 1) * addressSize);
+ }
+ }
+ }
+}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -87,6 +87,7 @@
private JNIHandles handles;
private Interpreter interpreter;
private StubRoutines stubRoutines;
+ private FileMapInfo fileMapInfo;
private Bytes bytes;
/** Flag indicating if JVMTI support is included in the build */
@@ -717,6 +718,16 @@
return vmregImpl;
}
+ public FileMapInfo getFileMapInfo() {
+ if (!isSharingEnabled()) {
+ return null;
+ }
+ if (fileMapInfo == null) {
+ fileMapInfo = new FileMapInfo();
+ }
+ return fileMapInfo;
+ }
+
public Bytes getBytes() {
if (bytes == null) {
bytes = new Bytes(debugger.getMachineDescription());
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -33,6 +33,7 @@
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
+import sun.jvm.hotspot.memory.FileMapInfo;
/** <P> This is a basic implementation of the TypeDataBase interface.
It allows an external type database builder to add types to be
@@ -294,6 +295,15 @@
// the locations searched.
Address loc1 = addr.getAddressAt(0);
+
+ if (VM.getVM().isSharingEnabled()) {
+ // Check if the value falls in the _md_region
+ FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
+ if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
+ return cdsFileMapInfo.getTypeForVptrAddress(loc1);
+ }
+ }
+
Address loc2 = null;
Address loc3 = null;
long offset2 = baseType.getSize();
--- a/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -496,29 +496,54 @@
// mapped. This structure gets written to a file. It is not a class, so
// that the compilers don't add any compiler-private data to it.
-const int NUM_SHARED_MAPS = 4;
+const int NUM_SHARED_MAPS = 9;
// Refer to FileMapInfo::_current_version in filemap.hpp
-const int CURRENT_ARCHIVE_VERSION = 1;
+const int CURRENT_ARCHIVE_VERSION = 3;
+
+typedef unsigned char* address;
+typedef uintptr_t uintx;
+typedef intptr_t intx;
struct FileMapHeader {
- int _magic; // identify file type.
- int _version; // (from enum, above.)
- size_t _alignment; // how shared archive should be aligned
+ int _magic; // identify file type.
+ int _crc; // header crc checksum.
+ int _version; // (from enum, above.)
+ size_t _alignment; // how shared archive should be aligned
+ int _obj_alignment; // value of ObjectAlignmentInBytes
+ address _narrow_oop_base; // compressed oop encoding base
+ int _narrow_oop_shift; // compressed oop encoding shift
+ bool _compact_strings; // value of CompactStrings
+ uintx _max_heap_size; // java max heap size during dumping
+ int _narrow_oop_mode; // compressed oop encoding mode
+ int _narrow_klass_shift; // save narrow klass base and shift
+ address _narrow_klass_base;
+ char* _misc_data_patching_start;
+ char* _read_only_tables_start;
+ address _cds_i2i_entry_code_buffers;
+ size_t _cds_i2i_entry_code_buffers_size;
+ size_t _core_spaces_size; // number of bytes allocated by the core spaces
+ // (mc, md, ro, rw and od).
- struct space_info {
- int _file_offset; // sizeof(this) rounded to vm page size
- char* _base; // copy-on-write base address
- size_t _capacity; // for validity checking
- size_t _used; // for setting space top on read
+ struct space_info {
+ int _crc; // crc checksum of the current space
+ size_t _file_offset; // sizeof(this) rounded to vm page size
+ union {
+ char* _base; // copy-on-write base address
+ intx _offset; // offset from the compressed oop encoding base, only used
+ // by archive heap space
+ } _addr;
+ size_t _used; // for setting space top on read
+ // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
+ // the C type matching the C++ bool type on any given platform.
+ // We assume the corresponding C type is char but licensees
+ // may need to adjust the type of these fields.
+ char _read_only; // read only space?
+ char _allow_exec; // executable code in space?
+ } _space[NUM_SHARED_MAPS];
- bool _read_only; // read only space?
- bool _allow_exec; // executable code in space?
-
- } _space[NUM_SHARED_MAPS];
-
- // Ignore the rest of the FileMapHeader. We don't need those fields here.
+// Ignore the rest of the FileMapHeader. We don't need those fields here.
};
static bool
@@ -677,7 +702,7 @@
if (_libsaproc_debug) {
for (int m = 0; m < NUM_SHARED_MAPS; m++) {
print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
- pheader->_space[m]._file_offset, pheader->_space[m]._base,
+ pheader->_space[m]._file_offset, pheader->_space[m]._addr._base,
pheader->_space[m]._used, pheader->_space[m]._read_only);
}
}
@@ -1058,7 +1083,7 @@
print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address);
struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
- // walk through the shared mappings -- we just have 4 of them.
+ // walk through the shared mappings -- we just have 9 of them.
// so, linear walking is okay.
for (int m = 0; m < NUM_SHARED_MAPS; m++) {
@@ -1066,7 +1091,7 @@
// and hence will be read by libproc. Besides, the file copy may be
// stale because the process might have modified those pages.
if (pheader->_space[m]._read_only) {
- jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._base;
+ jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._addr._base;
size_t usedSize = pheader->_space[m]._used;
if (address >= baseAddress && address < (baseAddress + usedSize)) {
// the given address falls in this shared heap area
--- a/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalManagement.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalManagement.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,154 @@
*/
package org.graalvm.compiler.hotspot.management;
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
+import org.graalvm.compiler.serviceprovider.ServiceProvider;
+
/**
- * Placeholder until next Graal update.
+ * Dynamically registers an MBean with the {@link ManagementFactory#getPlatformMBeanServer()}.
+ *
+ * Polling for an active platform MBean server is done by calling
+ * {@link MBeanServerFactory#findMBeanServer(String)} with an argument value of {@code null}. Once
+ * this returns an non-empty list, {@link ManagementFactory#getPlatformMBeanServer()} can be called
+ * to obtain a reference to the platform MBean server instance.
*/
-public final class HotSpotGraalManagement {
+@ServiceProvider(HotSpotGraalManagementRegistration.class)
+public final class HotSpotGraalManagement implements HotSpotGraalManagementRegistration {
+
+ private HotSpotGraalRuntimeMBean bean;
+ private volatile boolean needsRegistration = true;
+ HotSpotGraalManagement nextDeferred;
+
+ @Override
+ public void initialize(HotSpotGraalRuntime runtime) {
+ if (bean == null) {
+ if (runtime.getManagement() != this) {
+ throw new IllegalArgumentException("Cannot initialize a second management object for runtime " + runtime.getName());
+ }
+ try {
+ String name = runtime.getName().replace(':', '_');
+ ObjectName objectName = new ObjectName("org.graalvm.compiler.hotspot:type=" + name);
+ bean = new HotSpotGraalRuntimeMBean(objectName, runtime);
+ registration.add(this);
+ } catch (MalformedObjectNameException err) {
+ err.printStackTrace(TTY.out);
+ }
+ } else if (bean.getRuntime() != runtime) {
+ throw new IllegalArgumentException("Cannot change the runtime a management interface is associated with");
+ }
+ }
+
+ static final class RegistrationThread extends Thread {
+
+ private MBeanServer platformMBeanServer;
+ private HotSpotGraalManagement deferred;
+
+ RegistrationThread() {
+ super("HotSpotGraalManagement Bean Registration");
+ this.setPriority(Thread.MIN_PRIORITY);
+ this.setDaemon(true);
+ this.start();
+ }
+
+ /**
+ * Poll for active MBean server every 2 seconds.
+ */
+ private static final int POLL_INTERVAL_MS = 2000;
+
+ /**
+ * Adds a {@link HotSpotGraalManagement} to register with an active MBean server when one
+ * becomes available.
+ */
+ synchronized void add(HotSpotGraalManagement e) {
+ if (deferred != null) {
+ e.nextDeferred = deferred;
+ }
+ deferred = e;
+
+ // Notify the registration thread that there is now
+ // a deferred registration to process
+ notify();
+ }
+
+ /**
+ * Processes and clears any deferred registrations.
+ */
+ private void process() {
+ for (HotSpotGraalManagement m = deferred; m != null; m = m.nextDeferred) {
+ HotSpotGraalRuntimeMBean bean = m.bean;
+ if (m.needsRegistration && bean != null) {
+ try {
+ platformMBeanServer.registerMBean(bean, bean.getObjectName());
+ } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
+ e.printStackTrace(TTY.out);
+ // Registration failed - don't try again
+ m.bean = null;
+ }
+ m.needsRegistration = false;
+ }
+ }
+ deferred = null;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ synchronized (this) {
+ // Wait until there are deferred registrations to process
+ while (deferred == null) {
+ wait();
+ }
+ }
+ poll();
+ Thread.sleep(POLL_INTERVAL_MS);
+ } catch (InterruptedException e) {
+ // Be verbose about unexpected interruption and then continue
+ e.printStackTrace(TTY.out);
+ }
+ }
+ }
+
+ /**
+ * Checks for active MBean server and if available, processes deferred registrations.
+ */
+ synchronized void poll() {
+ if (platformMBeanServer == null) {
+ ArrayList<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
+ if (!servers.isEmpty()) {
+ platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
+ process();
+ }
+ } else {
+ process();
+ }
+ }
+ }
+
+ private static final RegistrationThread registration = new RegistrationThread();
+
+ @Override
+ public ObjectName poll(boolean sync) {
+ if (sync) {
+ registration.poll();
+ }
+ if (bean == null || needsRegistration) {
+ // initialize() has not been called, it failed or registration failed
+ return null;
+ }
+ return bean.getObjectName();
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalRuntimeMBean.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2018, 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.management;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
+import org.graalvm.compiler.options.OptionDescriptor;
+import org.graalvm.compiler.options.OptionDescriptors;
+import org.graalvm.compiler.options.OptionsParser;
+
+/**
+ * MBean used to access properties and operations of a {@link HotSpotGraalRuntime} instance.
+ */
+final class HotSpotGraalRuntimeMBean implements DynamicMBean {
+
+ /**
+ * The runtime instance to which this bean provides a management connection.
+ */
+ private final HotSpotGraalRuntime runtime;
+
+ /**
+ * The object name under which the bean is registered.
+ */
+ private final ObjectName objectName;
+
+ HotSpotGraalRuntimeMBean(ObjectName objectName, HotSpotGraalRuntime runtime) {
+ this.objectName = objectName;
+ this.runtime = runtime;
+ }
+
+ ObjectName getObjectName() {
+ return objectName;
+ }
+
+ HotSpotGraalRuntime getRuntime() {
+ return runtime;
+ }
+
+ private static final boolean DEBUG = Boolean.getBoolean(HotSpotGraalRuntimeMBean.class.getSimpleName() + ".debug");
+
+ @Override
+ public Object getAttribute(String name) throws AttributeNotFoundException {
+ String[] result = runtime.getOptionValues(name);
+ String value = result[0];
+ if (value == null) {
+ throw new AttributeNotFoundException(name);
+ }
+ if (DEBUG) {
+ System.out.printf("getAttribute: %s = %s (type: %s)%n", name, value, value == null ? "null" : value.getClass().getName());
+ }
+ return result[0];
+ }
+
+ @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality on the receiver is what we want")
+ @Override
+ public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException {
+ String name = attribute.getName();
+ Object value = attribute.getValue();
+ String svalue = String.valueOf(value);
+ if (DEBUG) {
+ System.out.printf("setAttribute: %s = %s (type: %s)%n", name, svalue, value == null ? "null" : value.getClass().getName());
+ }
+ String[] result = runtime.setOptionValues(new String[]{name}, new String[]{svalue});
+ if (result[0] != name) {
+ if (result[0] == null) {
+ throw new AttributeNotFoundException(name);
+ }
+ throw new InvalidAttributeValueException(result[0]);
+ }
+ }
+
+ @Override
+ public AttributeList getAttributes(String[] names) {
+ String[] values = runtime.getOptionValues(names);
+ AttributeList list = new AttributeList();
+ for (int i = 0; i < names.length; i++) {
+ String value = values[i];
+ String name = names[i];
+ if (value == null) {
+ TTY.printf("No such option named %s%n", name);
+ } else {
+ if (DEBUG) {
+ System.out.printf("getAttributes: %s = %s (type: %s)%n", name, value, value == null ? "null" : value.getClass().getName());
+ }
+ list.add(new Attribute(name, value));
+ }
+ }
+ return list;
+ }
+
+ @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality on the receiver is what we want")
+ @Override
+ public AttributeList setAttributes(AttributeList attributes) {
+ String[] names = new String[attributes.size()];
+ String[] values = new String[attributes.size()];
+
+ int i = 0;
+ for (Attribute attr : attributes.asList()) {
+ String name = attr.getName();
+ names[i] = name;
+ Object value = attr.getValue();
+ String svalue = String.valueOf(value);
+ values[i] = svalue;
+ if (DEBUG) {
+ System.out.printf("setAttributes: %s = %s (type: %s)%n", name, svalue, value == null ? "null" : value.getClass().getName());
+ }
+ i++;
+ }
+ String[] result = runtime.setOptionValues(names, values);
+ AttributeList setOk = new AttributeList();
+ i = 0;
+ for (Attribute attr : attributes.asList()) {
+ if (names[i] == result[i]) {
+ setOk.add(attr);
+ } else if (result[i] == null) {
+ TTY.printf("Error setting %s to %s: unknown option%n", attr.getName(), attr.getValue());
+ } else {
+ TTY.printf("Error setting %s to %s: %s%n", attr.getName(), attr.getValue(), result[i]);
+ }
+ i++;
+ }
+ return setOk;
+ }
+
+ @Override
+ public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+ try {
+ if (DEBUG) {
+ System.out.printf("invoke: %s%s%n", actionName, Arrays.asList(params));
+ }
+ Object retvalue = runtime.invokeManagementAction(actionName, params);
+ if (DEBUG) {
+ System.out.printf("invoke: %s%s = %s%n", actionName, Arrays.asList(params), retvalue);
+ }
+ return retvalue;
+ } catch (Exception ex) {
+ throw new ReflectionException(ex);
+ }
+ }
+
+ @Override
+ public MBeanInfo getMBeanInfo() {
+ List<MBeanAttributeInfo> attrs = new ArrayList<>();
+ for (OptionDescriptor option : getOptionDescriptors().getValues()) {
+ Class<?> optionValueType = option.getOptionValueType();
+ if (Enum.class.isAssignableFrom(optionValueType)) {
+ // Enum values are passed through
+ // the management interface as Strings.
+ optionValueType = String.class;
+ }
+ attrs.add(new MBeanAttributeInfo(option.getName(), optionValueType.getName(), option.getHelp(), true, true, false));
+ }
+ attrs.sort(new Comparator<MBeanAttributeInfo>() {
+ @Override
+ public int compare(MBeanAttributeInfo o1, MBeanAttributeInfo o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ });
+ MBeanOperationInfo[] ops = {
+ new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+ new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+ new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+ }, "void", MBeanOperationInfo.ACTION),
+ new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+ new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+ new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+ new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+ }, "void", MBeanOperationInfo.ACTION),
+ new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+ new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+ new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+ new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+ new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
+ new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
+ }, "void", MBeanOperationInfo.ACTION)
+ };
+
+ return new MBeanInfo(
+ HotSpotGraalRuntimeMBean.class.getName(),
+ "Graal",
+ attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
+ null, ops, null);
+ }
+
+ private static EconomicMap<String, OptionDescriptor> getOptionDescriptors() {
+ EconomicMap<String, OptionDescriptor> result = EconomicMap.create();
+ for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
+ for (OptionDescriptor option : set) {
+ result.put(option.getName(), option);
+ }
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/JMXServiceProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018, 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.management;
+
+import static java.lang.Thread.currentThread;
+
+import java.lang.management.ManagementFactory;
+import java.util.List;
+
+import org.graalvm.compiler.serviceprovider.ServiceProvider;
+import org.graalvm.compiler.serviceprovider.GraalServices.JMXService;
+
+import com.sun.management.ThreadMXBean;
+
+/**
+ * Implementation of {@link JMXService} for JDK 11 and later.
+ */
+@ServiceProvider(JMXService.class)
+public class JMXServiceProvider extends JMXService {
+ private final ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
+
+ @Override
+ protected long getThreadAllocatedBytes(long id) {
+ return threadMXBean.getThreadAllocatedBytes(id);
+ }
+
+ @Override
+ protected long getCurrentThreadCpuTime() {
+ long[] times = threadMXBean.getThreadCpuTime(new long[]{currentThread().getId()});
+ return times[0];
+ }
+
+ @Override
+ protected boolean isThreadAllocatedMemorySupported() {
+ return threadMXBean.isThreadAllocatedMemorySupported();
+ }
+
+ @Override
+ protected boolean isCurrentThreadCpuTimeSupported() {
+ return threadMXBean.isThreadCpuTimeSupported();
+ }
+
+ @Override
+ protected List<String> getInputArguments() {
+ return ManagementFactory.getRuntimeMXBean().getInputArguments();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/package-info.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/**
+ * JDK 11 and later versioned overlay for the {@code jdk.internal.vm.compiler.management} module.
+ * This cannot be used in JDK 10 where {@code jdk.internal.vm.compiler.management} is a
+ * non-upgradeable module.
+ */
+package org.graalvm.compiler.hotspot.management;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapImplTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicSet;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicMapImplTest {
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveNull() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create(10);
+ map.removeKey(null);
+ }
+
+ @Test
+ public void testInitFromHashSet() {
+ UnmodifiableEconomicSet<Integer> set = new UnmodifiableEconomicSet<Integer>() {
+
+ @Override
+ public boolean contains(Integer element) {
+ return element == 0;
+ }
+
+ @Override
+ public int size() {
+ return 1;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public Iterator<Integer> iterator() {
+ return new Iterator<Integer>() {
+
+ private boolean visited = false;
+
+ @Override
+ public boolean hasNext() {
+ return !visited;
+ }
+
+ @Override
+ public Integer next() {
+ if (visited) {
+ return null;
+ } else {
+ visited = true;
+ return 1;
+ }
+ }
+ };
+ }
+ };
+
+ EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.DEFAULT, set);
+ Assert.assertEquals(newSet.size(), 1);
+ }
+
+ @Test
+ public void testCopyHash() {
+ EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
+ set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+ EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.IDENTITY, set);
+ Assert.assertEquals(newSet.size(), 10);
+ newSet.remove(8);
+ newSet.remove(9);
+ Assert.assertEquals(newSet.size(), 8);
+ }
+
+ @Test
+ public void testNewEquivalence() {
+ EconomicSet<Integer> set = EconomicSet.create(new Equivalence() {
+ @Override
+ public boolean equals(Object a, Object b) {
+ return false;
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return 0;
+ }
+ });
+ set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+ Assert.assertTrue(set.add(new Integer(0)));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testMapPutNull() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ map.put(null, null);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapLargeTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Objects;
+import java.util.Random;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class EconomicMapLargeTest {
+
+ @Parameter(value = 0) public EconomicMap<Object, Object> testMap;
+ @Parameter(value = 1) public EconomicMap<Object, Object> referenceMap;
+ @Parameter(value = 2) public String name;
+
+ @Parameters(name = "{2}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.create(Equivalence.DEFAULT), "EconomicMap"},
+ new Object[]{EconomicMap.create(Equivalence.IDENTITY), EconomicMap.create(Equivalence.IDENTITY), "EconomicMap(IDENTITY)"},
+ new Object[]{EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE), EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE),
+ "EconomicMap(IDENTITY_WITH_SYSTEM_HASHCODE)"},
+ new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.wrapMap(new LinkedHashMap<>()), "EconomicMap<->wrapMap"},
+ new Object[]{EconomicMap.wrapMap(new LinkedHashMap<>()), EconomicMap.wrapMap(new LinkedHashMap<>()), "wrapMap"});
+ }
+
+ private static int[] createRandomRange(Random random, int count) {
+ int[] result = new int[count];
+ for (int i = 0; i < count; ++i) {
+ int range = random.nextInt(14);
+ if (range == 0 || range > 10) {
+ range = Integer.MAX_VALUE;
+ } else if (range == 10) {
+ range = 100;
+ }
+ result[i] = range;
+ }
+ return result;
+ }
+
+ private static final class BadHashClass {
+ private int value;
+
+ BadHashClass(int randomInt) {
+ this.value = randomInt;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof BadHashClass) {
+ BadHashClass badHashClass = (BadHashClass) other;
+ return badHashClass.value == value;
+ }
+ return false;
+ }
+ }
+
+ interface MapAction {
+ Object perform(EconomicMap<Object, Object> map, int randomInt);
+ }
+
+ static final Object EXISTING_VALUE = new Object();
+
+ static final MapAction[] INCREASE_ACTIONS = new MapAction[]{
+ (map, randomInt) -> map.put(randomInt, "value"),
+ (map, randomInt) -> map.get(randomInt)
+ };
+
+ static final MapAction[] ACTIONS = new MapAction[]{
+ (map, randomInt) -> map.removeKey(randomInt),
+ (map, randomInt) -> map.put(randomInt, "value"),
+ (map, randomInt) -> map.put(randomInt, null),
+ (map, randomInt) -> map.put(EXISTING_VALUE, randomInt),
+ (map, randomInt) -> {
+ if (randomInt == 0) {
+ map.clear();
+ }
+ return map.isEmpty();
+ },
+ (map, randomInt) -> map.containsKey(randomInt),
+ (map, randomInt) -> map.get(randomInt),
+ (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"),
+ (map, randomInt) -> {
+ if (randomInt == 0) {
+ map.replaceAll((key, value) -> Objects.toString(value) + "!");
+ }
+ return map.isEmpty();
+ }
+
+ };
+
+ @Test
+ public void testVeryLarge() {
+ testMap.clear();
+ referenceMap.clear();
+
+ Random random = new Random(0);
+ for (int i = 0; i < 200000; ++i) {
+ for (int j = 0; j < INCREASE_ACTIONS.length; ++j) {
+ int nextInt = random.nextInt(10000000);
+ MapAction action = INCREASE_ACTIONS[j];
+ Object result = action.perform(testMap, nextInt);
+ Object referenceResult = action.perform(referenceMap, nextInt);
+ Assert.assertEquals(result, referenceResult);
+ }
+ }
+ }
+
+ /**
+ * Tests a sequence of random operations on the map.
+ */
+ @Test
+ public void testAddRemove() {
+ testMap.clear();
+ referenceMap.clear();
+
+ for (int seed = 0; seed < 10; ++seed) {
+ Random random = new Random(seed);
+ int[] ranges = createRandomRange(random, ACTIONS.length);
+ int value = random.nextInt(10000);
+ for (int i = 0; i < value; ++i) {
+ for (int j = 0; j < ACTIONS.length; ++j) {
+ if (random.nextInt(ranges[j]) == 0) {
+ int nextInt = random.nextInt(100);
+ MapAction action = ACTIONS[j];
+ Object result = action.perform(testMap, nextInt);
+ Object referenceResult = action.perform(referenceMap, nextInt);
+ Assert.assertEquals(result, referenceResult);
+ if (j % 100 == 0) {
+ checkEquality(testMap, referenceMap);
+ }
+ }
+ }
+
+ if (random.nextInt(20) == 0) {
+ removeElement(random.nextInt(100), testMap, referenceMap);
+ }
+ }
+ }
+ }
+
+ private static void removeElement(int index, EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
+ Assert.assertEquals(referenceMap.size(), map.size());
+ MapCursor<?, ?> cursor = map.getEntries();
+ MapCursor<?, ?> referenceCursor = referenceMap.getEntries();
+ int z = 0;
+ while (cursor.advance()) {
+ Assert.assertTrue(referenceCursor.advance());
+ Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
+ Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
+ if (index == z) {
+ cursor.remove();
+ referenceCursor.remove();
+ }
+ ++z;
+ }
+
+ Assert.assertFalse(referenceCursor.advance());
+ }
+
+ private static void checkEquality(EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
+ Assert.assertEquals(referenceMap.size(), map.size());
+
+ // Check entries.
+ UnmodifiableMapCursor<?, ?> cursor = map.getEntries();
+ UnmodifiableMapCursor<?, ?> referenceCursor = referenceMap.getEntries();
+ while (cursor.advance()) {
+ Assert.assertTrue(referenceCursor.advance());
+ Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
+ Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
+ }
+
+ // Check keys.
+ Iterator<?> iterator = map.getKeys().iterator();
+ Iterator<?> referenceIterator = referenceMap.getKeys().iterator();
+ while (iterator.hasNext()) {
+ Assert.assertTrue(referenceIterator.hasNext());
+ Assert.assertEquals(iterator.next(), referenceIterator.next());
+ }
+
+ // Check values.
+ iterator = map.getValues().iterator();
+ referenceIterator = referenceMap.getValues().iterator();
+ while (iterator.hasNext()) {
+ Assert.assertTrue(referenceIterator.hasNext());
+ Assert.assertEquals(iterator.next(), referenceIterator.next());
+ }
+ Assert.assertFalse(referenceIterator.hasNext());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.LinkedHashMap;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicMapTest {
+
+ @Test
+ public void testMapGetDefault() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ map.put(0, 1);
+ Assert.assertEquals(map.get(0, 2), Integer.valueOf(1));
+ Assert.assertEquals(map.get(1, 2), Integer.valueOf(2));
+ }
+
+ @Test
+ public void testMapPutAll() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ EconomicMap<Integer, Integer> newMap = EconomicMap.wrapMap(new LinkedHashMap<>());
+ newMap.put(1, 1);
+ newMap.put(2, 4);
+ map.putAll(newMap);
+ Assert.assertEquals(map.size(), 2);
+
+ UnmodifiableEconomicMap<Integer, Integer> unmodifiableEconomicMap = EconomicMap.create(newMap);
+
+ map.removeKey(1);
+ map.put(2, 2);
+ map.put(3, 9);
+
+ map.putAll(unmodifiableEconomicMap);
+ Assert.assertEquals(map.size(), 3);
+ Assert.assertEquals(map.get(2), Integer.valueOf(4));
+ }
+
+ @Test
+ public void testToString() {
+ EconomicMap<Integer, Integer> map = EconomicMap.create();
+ map.put(0, 0);
+ map.put(1, 1);
+ Assert.assertEquals(map.toString(), "map(size=2, {(0,0),(1,1)})");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicSetTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicSetTest {
+
+ @Test
+ public void testUtilities() {
+ EconomicSet<Integer> set = EconomicSet.create(0);
+ set.add(0);
+ Assert.assertTrue(set.add(1));
+ Assert.assertEquals(set.size(), 2);
+ Assert.assertFalse(set.add(1));
+ Assert.assertEquals(set.size(), 2);
+ set.remove(1);
+ Assert.assertEquals(set.size(), 1);
+ set.remove(2);
+ Assert.assertEquals(set.size(), 1);
+ Assert.assertTrue(set.add(1));
+ set.clear();
+ Assert.assertEquals(set.size(), 0);
+ }
+
+ @Test
+ public void testAddAll() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1, 0));
+ Assert.assertEquals(set.size(), 2);
+
+ EconomicSet<Integer> newSet = EconomicSet.create();
+ newSet.addAll(Arrays.asList(1, 2));
+ Assert.assertEquals(newSet.size(), 2);
+ newSet.addAll(set);
+ Assert.assertEquals(newSet.size(), 3);
+ }
+
+ @Test
+ public void testRemoveAll() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1));
+
+ set.removeAll(Arrays.asList(1, 2));
+ Assert.assertEquals(set.size(), 1);
+
+ set.removeAll(EconomicSet.create(set));
+ Assert.assertEquals(set.size(), 0);
+ }
+
+ @Test
+ public void testRetainAll() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1, 2));
+
+ EconomicSet<Integer> newSet = EconomicSet.create();
+ newSet.addAll(Arrays.asList(2, 3));
+
+ set.retainAll(newSet);
+ Assert.assertEquals(set.size(), 1);
+ }
+
+ @Test
+ public void testToArray() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1));
+ Assert.assertArrayEquals(set.toArray(new Integer[2]), new Integer[]{0, 1});
+ }
+
+ @Test
+ public void testToString() {
+ EconomicSet<Integer> set = EconomicSet.create();
+ set.addAll(Arrays.asList(0, 1));
+ Assert.assertEquals(set.toString(), "set(size=2, {0,1})");
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testToUnalignedArray() {
+ Assert.assertArrayEquals(EconomicSet.create().toArray(new Integer[2]), new Integer[0]);
+ }
+
+ @Test
+ public void testSetRemoval() {
+ ArrayList<Integer> initialList = new ArrayList<>();
+ ArrayList<Integer> removalList = new ArrayList<>();
+ ArrayList<Integer> finalList = new ArrayList<>();
+ EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
+ set.add(1);
+ set.add(2);
+ set.add(3);
+ set.add(4);
+ set.add(5);
+ set.add(6);
+ set.add(7);
+ set.add(8);
+ set.add(9);
+ Iterator<Integer> i1 = set.iterator();
+ while (i1.hasNext()) {
+ initialList.add(i1.next());
+ }
+ int size = 0;
+ Iterator<Integer> i2 = set.iterator();
+ while (i2.hasNext()) {
+ Integer elem = i2.next();
+ if (size++ < 8) {
+ i2.remove();
+ }
+ removalList.add(elem);
+ }
+ Iterator<Integer> i3 = set.iterator();
+ while (i3.hasNext()) {
+ finalList.add(i3.next());
+ }
+ Assert.assertEquals(initialList, removalList);
+ Assert.assertEquals(1, finalList.size());
+ Assert.assertEquals(new Integer(9), finalList.get(0));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EquivalenceTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import jdk.internal.vm.compiler.collections.Equivalence;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EquivalenceTest {
+
+ private static final String TEST_STRING = "Graal";
+ private static final String TEST_STRING2 = "Graal2";
+
+ @Test
+ public void testDEFAULT() {
+ Assert.assertTrue(Equivalence.DEFAULT.equals(TEST_STRING, new String(TEST_STRING)));
+ Assert.assertEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(new String(TEST_STRING)));
+ Assert.assertFalse(Equivalence.DEFAULT.equals(TEST_STRING, TEST_STRING2));
+ Assert.assertNotEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(TEST_STRING2));
+ }
+
+ @Test
+ public void testIDENTITY() {
+ Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, new String(TEST_STRING)));
+ Assert.assertEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(new String(TEST_STRING)));
+ Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, TEST_STRING2));
+ Assert.assertNotEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(TEST_STRING2));
+ }
+
+ @Test
+ public void testIDENTITYWITHSYSTEMHASHCODE() {
+ Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, new String(TEST_STRING)));
+ Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(new String(TEST_STRING)));
+ Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, TEST_STRING2));
+ Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING2));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/PairTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import jdk.internal.vm.compiler.collections.Pair;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PairTest {
+
+ @Test
+ public void testCreate() {
+ Assert.assertEquals(Pair.create(null, null), Pair.empty());
+ Assert.assertNotEquals(Pair.create(null, null), null);
+ Assert.assertEquals(Pair.createLeft(null), Pair.empty());
+ Assert.assertEquals(Pair.createRight(null), Pair.empty());
+ Assert.assertEquals(Pair.create(1, null), Pair.createLeft(1));
+ Assert.assertEquals(Pair.create(null, 1), Pair.createRight(1));
+ }
+
+ @Test
+ public void testUtilities() {
+ Pair<Integer, Integer> pair = Pair.create(1, null);
+ Assert.assertEquals(pair.getLeft(), Integer.valueOf(1));
+ Assert.assertEquals(pair.getRight(), null);
+ Assert.assertEquals(pair.toString(), "(1, null)");
+ Assert.assertEquals(pair.hashCode(), Pair.createLeft(1).hashCode());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMap.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+/**
+ * Memory efficient map data structure.
+ *
+ * @since 1.0
+ */
+public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
+
+ /**
+ * Associates {@code value} with {@code key} in this map. If the map previously contained a
+ * mapping for {@code key}, the old value is replaced by {@code value}.
+ *
+ * @return the previous value associated with {@code key}, or {@code null} if there was no
+ * mapping for {@code key}.
+ * @since 1.0
+ */
+ V put(K key, V value);
+
+ /**
+ * Copies all of the mappings from {@code other} to this map.
+ *
+ * @since 1.0
+ */
+ default void putAll(EconomicMap<K, V> other) {
+ MapCursor<K, V> e = other.getEntries();
+ while (e.advance()) {
+ put(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Copies all of the mappings from {@code other} to this map.
+ *
+ * @since 1.0
+ */
+ default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
+ UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
+ while (entry.advance()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /**
+ * Removes all of the mappings from this map. The map will be empty after this call returns.
+ *
+ * @since 1.0
+ */
+ void clear();
+
+ /**
+ * Removes the mapping for {@code key} from this map if it is present. The map will not contain
+ * a mapping for {@code key} once the call returns.
+ *
+ * @return the previous value associated with {@code key}, or {@code null} if there was no
+ * mapping for {@code key}.
+ * @since 1.0
+ */
+ V removeKey(K key);
+
+ /**
+ * Returns a {@link MapCursor} view of the mappings contained in this map.
+ *
+ * @since 1.0
+ */
+ @Override
+ MapCursor<K, V> getEntries();
+
+ /**
+ * Replaces each entry's value with the result of invoking {@code function} on that entry until
+ * all entries have been processed or the function throws an exception. Exceptions thrown by the
+ * function are relayed to the caller.
+ *
+ * @since 1.0
+ */
+ void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
+
+ /**
+ * 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
+ */
+ static <K, V> EconomicMap<K, V> create() {
+ return EconomicMap.create(Equivalence.DEFAULT);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set with the default
+ * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
+ * capacity.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(int initialCapacity) {
+ return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set with the given comparison
+ * strategy for keys.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
+ return EconomicMapImpl.create(strategy, false);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set with the default
+ * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
+ * specified existing map.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
+ return EconomicMap.create(Equivalence.DEFAULT, m);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set and copies all elements from
+ * the specified existing map.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
+ return EconomicMapImpl.create(strategy, m, false);
+ }
+
+ /**
+ * Creates a new map that guarantees insertion order on the key set and initializes with a
+ * specified capacity.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
+ return EconomicMapImpl.create(strategy, initialCapacity, false);
+ }
+
+ /**
+ * Wraps an existing {@link Map} as an {@link EconomicMap}.
+ *
+ * @since 1.0
+ */
+ static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
+ return new EconomicMap<K, V>() {
+
+ @Override
+ public V get(K key) {
+ V result = map.get(key);
+ return result;
+ }
+
+ @Override
+ public V put(K key, V value) {
+ V result = map.put(key, value);
+ return result;
+ }
+
+ @Override
+ public int size() {
+ int result = map.size();
+ return result;
+ }
+
+ @Override
+ public boolean containsKey(K key) {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public void clear() {
+ map.clear();
+ }
+
+ @Override
+ public V removeKey(K key) {
+ V result = map.remove(key);
+ return result;
+ }
+
+ @Override
+ public Iterable<V> getValues() {
+ return map.values();
+ }
+
+ @Override
+ public Iterable<K> getKeys() {
+ return map.keySet();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ @Override
+ public MapCursor<K, V> getEntries() {
+ Iterator<java.util.Map.Entry<K, V>> iterator = map.entrySet().iterator();
+ return new MapCursor<K, V>() {
+
+ private Map.Entry<K, V> current;
+
+ @Override
+ public boolean advance() {
+ boolean result = iterator.hasNext();
+ if (result) {
+ current = iterator.next();
+ }
+
+ return result;
+ }
+
+ @Override
+ public K getKey() {
+ return current.getKey();
+ }
+
+ @Override
+ public V getValue() {
+ return current.getValue();
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ }
+ };
+ }
+
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ map.replaceAll(function);
+ }
+ };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMapImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,857 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+/**
+ * Implementation of a map with a memory-efficient structure that always preserves insertion order
+ * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal
+ * {@link #INITIAL_CAPACITY} or smaller 256.
+ *
+ * The key/value pairs are kept in an expanding flat object array with keys at even indices and
+ * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there
+ * is no additional hash data structure and comparisons are done via linear checking of the
+ * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an
+ * object identity comparison), this limit below which the map is without an actual hash table is
+ * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}.
+ *
+ * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash
+ * array where an entry of 0 means no hit and otherwise denotes the entry number in the
+ * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit
+ * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of
+ * integer values in other cases.
+ *
+ * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take
+ * the place of the values in the {@link #entries} array.
+ *
+ * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the
+ * map falls below a specific threshold, the map will be compressed via the
+ * {@link #maybeCompress(int)} method.
+ */
+final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
+
+ /**
+ * Initial number of key/value pair entries that is allocated in the first entries array.
+ */
+ private static final int INITIAL_CAPACITY = 4;
+
+ /**
+ * Maximum number of entries that are moved linearly forward if a key is removed.
+ */
+ private static final int COMPRESS_IMMEDIATE_CAPACITY = 8;
+
+ /**
+ * Minimum number of key/value pair entries added when the entries array is increased in size.
+ */
+ private static final int MIN_CAPACITY_INCREASE = 8;
+
+ /**
+ * Number of entries above which a hash table is created.
+ */
+ private static final int HASH_THRESHOLD = 4;
+
+ /**
+ * Number of entries above which a hash table is created when equality can be checked with
+ * object identity.
+ */
+ private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8;
+
+ /**
+ * Maximum number of entries allowed in the map.
+ */
+ private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1;
+
+ /**
+ * Number of entries above which more than 1 byte is necessary for the hash index.
+ */
+ private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1);
+
+ /**
+ * Number of entries above which more than 2 bytes are are necessary for the hash index.
+ */
+ private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE);
+
+ /**
+ * Total number of entries (actual entries plus deleted entries).
+ */
+ private int totalEntries;
+
+ /**
+ * Number of deleted entries.
+ */
+ private int deletedEntries;
+
+ /**
+ * Entries array with even indices storing keys and odd indices storing values.
+ */
+ private Object[] entries;
+
+ /**
+ * Hash array that is interpreted either as byte or short or int array depending on number of
+ * map entries.
+ */
+ private byte[] hashArray;
+
+ /**
+ * The strategy used for comparing keys or {@code null} for denoting special strategy
+ * {@link Equivalence#IDENTITY}.
+ */
+ private final Equivalence strategy;
+
+ /**
+ * Intercept method for debugging purposes.
+ */
+ private static <K, V> EconomicMapImpl<K, V> intercept(EconomicMapImpl<K, V> map) {
+ return map;
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, isSet));
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, int initialCapacity, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, initialCapacity, isSet));
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, other, isSet));
+ }
+
+ public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
+ return intercept(new EconomicMapImpl<>(strategy, other, isSet));
+ }
+
+ private EconomicMapImpl(Equivalence strategy, boolean isSet) {
+ if (strategy == Equivalence.IDENTITY) {
+ this.strategy = null;
+ } else {
+ this.strategy = strategy;
+ }
+ this.isSet = isSet;
+ }
+
+ private EconomicMapImpl(Equivalence strategy, int initialCapacity, boolean isSet) {
+ this(strategy, isSet);
+ init(initialCapacity);
+ }
+
+ private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
+ this(strategy, isSet);
+ if (!initFrom(other)) {
+ init(other.size());
+ putAll(other);
+ }
+ }
+
+ private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
+ this(strategy, isSet);
+ if (!initFrom(other)) {
+ init(other.size());
+ addAll(other);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private boolean initFrom(Object o) {
+ if (o instanceof EconomicMapImpl) {
+ EconomicMapImpl<K, V> otherMap = (EconomicMapImpl<K, V>) o;
+ // We are only allowed to directly copy if the strategies of the two maps are the same.
+ if (strategy == otherMap.strategy) {
+ totalEntries = otherMap.totalEntries;
+ deletedEntries = otherMap.deletedEntries;
+ if (otherMap.entries != null) {
+ entries = otherMap.entries.clone();
+ }
+ if (otherMap.hashArray != null) {
+ hashArray = otherMap.hashArray.clone();
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void init(int size) {
+ if (size > INITIAL_CAPACITY) {
+ entries = new Object[size << 1];
+ }
+ }
+
+ /**
+ * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from
+ * other map on construction.
+ */
+ private static final class CollisionLink {
+
+ CollisionLink(Object value, int next) {
+ this.value = value;
+ this.next = next;
+ }
+
+ final Object value;
+
+ /**
+ * Index plus one of the next entry in the collision link chain.
+ */
+ final int next;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(K key) {
+ Objects.requireNonNull(key);
+
+ int index = find(key);
+ if (index != -1) {
+ return (V) getValue(index);
+ }
+ return null;
+ }
+
+ private int find(K key) {
+ if (hasHashArray()) {
+ return findHash(key);
+ } else {
+ return findLinear(key);
+ }
+ }
+
+ private int findLinear(K key) {
+ for (int i = 0; i < totalEntries; i++) {
+ Object entryKey = entries[i << 1];
+ if (entryKey != null && compareKeys(key, entryKey)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private boolean compareKeys(Object key, Object entryKey) {
+ if (key == entryKey) {
+ return true;
+ }
+ if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+ if (strategy == Equivalence.DEFAULT) {
+ return key.equals(entryKey);
+ } else {
+ return strategy.equals(key, entryKey);
+ }
+ }
+ return false;
+ }
+
+ private int findHash(K key) {
+ int index = getHashArray(getHashIndex(key)) - 1;
+ if (index != -1) {
+ Object entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ return index;
+ } else {
+ Object entryValue = getRawValue(index);
+ if (entryValue instanceof CollisionLink) {
+ return findWithCollision(key, (CollisionLink) entryValue);
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private int findWithCollision(K key, CollisionLink initialEntryValue) {
+ int index;
+ Object entryKey;
+ CollisionLink entryValue = initialEntryValue;
+ while (true) {
+ CollisionLink collisionLink = entryValue;
+ index = collisionLink.next;
+ entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ return index;
+ } else {
+ Object value = getRawValue(index);
+ if (value instanceof CollisionLink) {
+ entryValue = (CollisionLink) getRawValue(index);
+ } else {
+ return -1;
+ }
+ }
+ }
+ }
+
+ private int getHashArray(int index) {
+ if (entries.length < LARGE_HASH_THRESHOLD) {
+ return (hashArray[index] & 0xFF);
+ } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+ int adjustedIndex = index << 1;
+ return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8);
+ } else {
+ int adjustedIndex = index << 2;
+ return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24);
+ }
+ }
+
+ private void setHashArray(int index, int value) {
+ if (entries.length < LARGE_HASH_THRESHOLD) {
+ hashArray[index] = (byte) value;
+ } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+ int adjustedIndex = index << 1;
+ hashArray[adjustedIndex] = (byte) value;
+ hashArray[adjustedIndex + 1] = (byte) (value >> 8);
+ } else {
+ int adjustedIndex = index << 2;
+ hashArray[adjustedIndex] = (byte) value;
+ hashArray[adjustedIndex + 1] = (byte) (value >> 8);
+ hashArray[adjustedIndex + 2] = (byte) (value >> 16);
+ hashArray[adjustedIndex + 3] = (byte) (value >> 24);
+ }
+ }
+
+ private int findAndRemoveHash(Object key) {
+ int hashIndex = getHashIndex(key);
+ int index = getHashArray(hashIndex) - 1;
+ if (index != -1) {
+ Object entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ Object value = getRawValue(index);
+ int nextIndex = -1;
+ if (value instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) value;
+ nextIndex = collisionLink.next;
+ }
+ setHashArray(hashIndex, nextIndex + 1);
+ return index;
+ } else {
+ Object entryValue = getRawValue(index);
+ if (entryValue instanceof CollisionLink) {
+ return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index);
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) {
+ int index;
+ Object entryKey;
+ CollisionLink entryValue = initialEntryValue;
+ int lastIndex = initialIndexValue;
+ while (true) {
+ CollisionLink collisionLink = entryValue;
+ index = collisionLink.next;
+ entryKey = getKey(index);
+ if (compareKeys(key, entryKey)) {
+ Object value = getRawValue(index);
+ if (value instanceof CollisionLink) {
+ CollisionLink thisCollisionLink = (CollisionLink) value;
+ setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next));
+ } else {
+ setRawValue(lastIndex, collisionLink.value);
+ }
+ return index;
+ } else {
+ Object value = getRawValue(index);
+ if (value instanceof CollisionLink) {
+ entryValue = (CollisionLink) getRawValue(index);
+ lastIndex = index;
+ } else {
+ return -1;
+ }
+ }
+ }
+ }
+
+ private int getHashIndex(Object key) {
+ int hash;
+ if (strategy != null && strategy != Equivalence.DEFAULT) {
+ if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+ hash = System.identityHashCode(key);
+ } else {
+ hash = strategy.hashCode(key);
+ }
+ } else {
+ hash = key.hashCode();
+ }
+ hash = hash ^ (hash >>> 16);
+ return hash & (getHashTableSize() - 1);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V put(K key, V value) {
+ if (key == null) {
+ throw new UnsupportedOperationException("null not supported as key!");
+ }
+ int index = find(key);
+ if (index != -1) {
+ Object oldValue = getValue(index);
+ setValue(index, value);
+ return (V) oldValue;
+ }
+
+ int nextEntryIndex = totalEntries;
+ if (entries == null) {
+ entries = new Object[INITIAL_CAPACITY << 1];
+ } else if (entries.length == nextEntryIndex << 1) {
+ grow();
+
+ assert entries.length > totalEntries << 1;
+ // Can change if grow is actually compressing.
+ nextEntryIndex = totalEntries;
+ }
+
+ setKey(nextEntryIndex, key);
+ setValue(nextEntryIndex, value);
+ totalEntries++;
+
+ if (hasHashArray()) {
+ // Rehash on collision if hash table is more than three quarters full.
+ boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1)));
+ putHashEntry(key, nextEntryIndex, rehashOnCollision);
+ } else if (totalEntries > getHashThreshold()) {
+ createHash();
+ }
+
+ return null;
+ }
+
+ /**
+ * Number of entries above which a hash table should be constructed.
+ */
+ private int getHashThreshold() {
+ if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+ return HASH_THRESHOLD_IDENTITY_COMPARE;
+ } else {
+ return HASH_THRESHOLD;
+ }
+ }
+
+ private void grow() {
+ int entriesLength = entries.length;
+ int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2);
+ if (newSize > MAX_ELEMENT_COUNT) {
+ throw new UnsupportedOperationException("map grown too large!");
+ }
+ Object[] newEntries = new Object[newSize << 1];
+ System.arraycopy(entries, 0, newEntries, 0, entriesLength);
+ entries = newEntries;
+ if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) ||
+ (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) {
+ // Rehash in order to change number of bits reserved for hash indices.
+ createHash();
+ }
+ }
+
+ /**
+ * Compresses the graph if there is a large number of deleted entries and returns the translated
+ * new next index.
+ */
+ private int maybeCompress(int nextIndex) {
+ if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) {
+ return compressLarge(nextIndex);
+ }
+ return nextIndex;
+ }
+
+ /**
+ * Compresses the graph and returns the translated new next index.
+ */
+ private int compressLarge(int nextIndex) {
+ int size = INITIAL_CAPACITY;
+ int remaining = totalEntries - deletedEntries;
+
+ while (size <= remaining) {
+ size += Math.max(MIN_CAPACITY_INCREASE, size >> 1);
+ }
+
+ Object[] newEntries = new Object[size << 1];
+ int z = 0;
+ int newNextIndex = remaining;
+ for (int i = 0; i < totalEntries; ++i) {
+ Object key = getKey(i);
+ if (i == nextIndex) {
+ newNextIndex = z;
+ }
+ if (key != null) {
+ newEntries[z << 1] = key;
+ newEntries[(z << 1) + 1] = getValue(i);
+ z++;
+ }
+ }
+
+ this.entries = newEntries;
+ totalEntries = z;
+ deletedEntries = 0;
+ if (z <= getHashThreshold()) {
+ this.hashArray = null;
+ } else {
+ createHash();
+ }
+ return newNextIndex;
+ }
+
+ private int getHashTableSize() {
+ if (entries.length < LARGE_HASH_THRESHOLD) {
+ return hashArray.length;
+ } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+ return hashArray.length >> 1;
+ } else {
+ return hashArray.length >> 2;
+ }
+ }
+
+ private void createHash() {
+ int entryCount = size();
+
+ // Calculate smallest 2^n that is greater number of entries.
+ int size = getHashThreshold();
+ while (size <= entryCount) {
+ size <<= 1;
+ }
+
+ // Give extra size to avoid collisions.
+ size <<= 1;
+
+ if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) {
+ // Every entry has 4 bytes.
+ size <<= 2;
+ } else if (this.entries.length >= LARGE_HASH_THRESHOLD) {
+ // Every entry has 2 bytes.
+ size <<= 1;
+ } else {
+ // Entries are very small => give extra size to further reduce collisions.
+ size <<= 1;
+ }
+
+ hashArray = new byte[size];
+ for (int i = 0; i < totalEntries; i++) {
+ Object entryKey = getKey(i);
+ if (entryKey != null) {
+ putHashEntry(entryKey, i, false);
+ }
+ }
+ }
+
+ private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) {
+ int hashIndex = getHashIndex(key);
+ int oldIndex = getHashArray(hashIndex) - 1;
+ if (oldIndex != -1 && rehashOnCollision) {
+ this.createHash();
+ return;
+ }
+ setHashArray(hashIndex, entryIndex + 1);
+ Object value = getRawValue(entryIndex);
+ if (oldIndex != -1) {
+ assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle";
+ if (value instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) value;
+ setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex));
+ } else {
+ setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex));
+ }
+ } else {
+ if (value instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) value;
+ setRawValue(entryIndex, collisionLink.value);
+ }
+ }
+ }
+
+ @Override
+ public int size() {
+ return totalEntries - deletedEntries;
+ }
+
+ @Override
+ public boolean containsKey(K key) {
+ return find(key) != -1;
+ }
+
+ @Override
+ public void clear() {
+ entries = null;
+ hashArray = null;
+ totalEntries = deletedEntries = 0;
+ }
+
+ private boolean hasHashArray() {
+ return hashArray != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V removeKey(K key) {
+ if (key == null) {
+ throw new UnsupportedOperationException("null not supported as key!");
+ }
+ int index;
+ if (hasHashArray()) {
+ index = this.findAndRemoveHash(key);
+ } else {
+ index = this.findLinear(key);
+ }
+
+ if (index != -1) {
+ Object value = getValue(index);
+ remove(index);
+ return (V) value;
+ }
+ return null;
+ }
+
+ /**
+ * Removes the element at the specific index and returns the index of the next element. This can
+ * be a different value if graph compression was triggered.
+ */
+ private int remove(int indexToRemove) {
+ int index = indexToRemove;
+ int entriesAfterIndex = totalEntries - index - 1;
+ int result = index + 1;
+
+ // Without hash array, compress immediately.
+ if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) {
+ while (index < totalEntries - 1) {
+ setKey(index, getKey(index + 1));
+ setRawValue(index, getRawValue(index + 1));
+ index++;
+ }
+ result--;
+ }
+
+ setKey(index, null);
+ setRawValue(index, null);
+ if (index == totalEntries - 1) {
+ // Make sure last element is always non-null.
+ totalEntries--;
+ while (index > 0 && getKey(index - 1) == null) {
+ totalEntries--;
+ deletedEntries--;
+ index--;
+ }
+ } else {
+ deletedEntries++;
+ result = maybeCompress(result);
+ }
+
+ return result;
+ }
+
+ private abstract class SparseMapIterator<E> implements Iterator<E> {
+
+ protected int current;
+
+ @Override
+ public boolean hasNext() {
+ return current < totalEntries;
+ }
+
+ @Override
+ public void remove() {
+ if (hasHashArray()) {
+ EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1));
+ }
+ current = EconomicMapImpl.this.remove(current - 1);
+ }
+ }
+
+ @Override
+ public Iterable<V> getValues() {
+ return new Iterable<V>() {
+ @Override
+ public Iterator<V> iterator() {
+ return new SparseMapIterator<V>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public V next() {
+ Object result;
+ while (true) {
+ result = getValue(current);
+ if (result == null && getKey(current) == null) {
+ // values can be null, double-check if key is also null
+ current++;
+ } else {
+ current++;
+ break;
+ }
+ }
+ return (V) result;
+ }
+ };
+ }
+ };
+ }
+
+ @Override
+ public Iterable<K> getKeys() {
+ return this;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.size() == 0;
+ }
+
+ @Override
+ public MapCursor<K, V> getEntries() {
+ return new MapCursor<K, V>() {
+ int current = -1;
+
+ @Override
+ public boolean advance() {
+ current++;
+ if (current >= totalEntries) {
+ return false;
+ } else {
+ while (EconomicMapImpl.this.getKey(current) == null) {
+ // Skip over null entries
+ current++;
+ }
+ return true;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public K getKey() {
+ return (K) EconomicMapImpl.this.getKey(current);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V getValue() {
+ return (V) EconomicMapImpl.this.getValue(current);
+ }
+
+ @Override
+ public void remove() {
+ if (hasHashArray()) {
+ EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current));
+ }
+ current = EconomicMapImpl.this.remove(current) - 1;
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ for (int i = 0; i < totalEntries; i++) {
+ Object entryKey = getKey(i);
+ if (entryKey != null) {
+ Object newValue = function.apply((K) entryKey, (V) getValue(i));
+ setValue(i, newValue);
+ }
+ }
+ }
+
+ private Object getKey(int index) {
+ return entries[index << 1];
+ }
+
+ private void setKey(int index, Object newValue) {
+ entries[index << 1] = newValue;
+ }
+
+ private void setValue(int index, Object newValue) {
+ Object oldValue = getRawValue(index);
+ if (oldValue instanceof CollisionLink) {
+ CollisionLink collisionLink = (CollisionLink) oldValue;
+ setRawValue(index, new CollisionLink(newValue, collisionLink.next));
+ } else {
+ setRawValue(index, newValue);
+ }
+ }
+
+ private void setRawValue(int index, Object newValue) {
+ entries[(index << 1) + 1] = newValue;
+ }
+
+ private Object getRawValue(int index) {
+ return entries[(index << 1) + 1];
+ }
+
+ private Object getValue(int index) {
+ Object object = getRawValue(index);
+ if (object instanceof CollisionLink) {
+ return ((CollisionLink) object).value;
+ }
+ return object;
+ }
+
+ private final boolean isSet;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(isSet ? "set(size=" : "map(size=").append(size()).append(", {");
+ String sep = "";
+ MapCursor<K, V> cursor = getEntries();
+ while (cursor.advance()) {
+ builder.append(sep);
+ if (isSet) {
+ builder.append(cursor.getKey());
+ } else {
+ builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append(")");
+ }
+ sep = ",";
+ }
+ builder.append("})");
+ return builder.toString();
+ }
+
+ @Override
+ public Iterator<K> iterator() {
+ return new SparseMapIterator<K>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public K next() {
+ Object result;
+ while ((result = getKey(current++)) == null) {
+ // skip null entries
+ }
+ return (K) result;
+ }
+ };
+ }
+
+ @Override
+ public boolean contains(K element) {
+ return containsKey(element);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean add(K element) {
+ return put(element, (V) element) == null;
+ }
+
+ @Override
+ public void remove(K element) {
+ removeKey(element);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicSet.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Iterator;
+
+/**
+ * Memory efficient set data structure.
+ *
+ * @since 1.0
+ */
+public interface EconomicSet<E> extends UnmodifiableEconomicSet<E> {
+
+ /**
+ * 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
+ */
+ boolean add(E element);
+
+ /**
+ * Removes {@code element} from this set if it is present. This set will not contain
+ * {@code element} once the call returns.
+ *
+ * @since 1.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
+ */
+ void clear();
+
+ /**
+ * Adds all of the elements in {@code other} to this set if they're not already present.
+ *
+ * @since 1.0
+ */
+ default void addAll(EconomicSet<E> other) {
+ addAll(other.iterator());
+ }
+
+ /**
+ * Adds all of the elements in {@code values} to this set if they're not already present.
+ *
+ * @since 1.0
+ */
+ default void addAll(Iterable<E> values) {
+ addAll(values.iterator());
+ }
+
+ /**
+ * Adds all of the elements enumerated by {@code iterator} to this set if they're not already
+ * present.
+ *
+ * @since 1.0
+ */
+ default void addAll(Iterator<E> iterator) {
+ while (iterator.hasNext()) {
+ add(iterator.next());
+ }
+ }
+
+ /**
+ * Removes from this set all of its elements that are contained in {@code other}.
+ *
+ * @since 1.0
+ */
+ default void removeAll(EconomicSet<E> other) {
+ removeAll(other.iterator());
+ }
+
+ /**
+ * Removes from this set all of its elements that are contained in {@code values}.
+ *
+ * @since 1.0
+ */
+ default void removeAll(Iterable<E> values) {
+ removeAll(values.iterator());
+ }
+
+ /**
+ * Removes from this set all of its elements that are enumerated by {@code iterator}.
+ *
+ * @since 1.0
+ */
+ default void removeAll(Iterator<E> iterator) {
+ while (iterator.hasNext()) {
+ remove(iterator.next());
+ }
+ }
+
+ /**
+ * Removes from this set all of its elements that are not contained in {@code other}.
+ *
+ * @since 1.0
+ */
+ default void retainAll(EconomicSet<E> other) {
+ Iterator<E> iterator = iterator();
+ while (iterator.hasNext()) {
+ E key = iterator.next();
+ if (!other.contains(key)) {
+ iterator.remove();
+ }
+ }
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements with the
+ * default {@link Equivalence#DEFAULT} comparison strategy.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create() {
+ return EconomicSet.create(Equivalence.DEFAULT);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(Equivalence strategy) {
+ return EconomicMapImpl.create(strategy, true);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements with the
+ * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
+ * specified collection.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(int initialCapacity) {
+ return EconomicSet.create(Equivalence.DEFAULT, initialCapacity);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements with the
+ * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
+ * specified collection.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(UnmodifiableEconomicSet<E> c) {
+ return EconomicSet.create(Equivalence.DEFAULT, c);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements and
+ * initializes with the given capacity.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(Equivalence strategy, int initialCapacity) {
+ return EconomicMapImpl.create(strategy, initialCapacity, true);
+ }
+
+ /**
+ * Creates a new set guaranteeing insertion order when iterating over its elements and inserts
+ * all elements of the specified collection.
+ *
+ * @since 1.0
+ */
+ static <E> EconomicSet<E> create(Equivalence strategy, UnmodifiableEconomicSet<E> c) {
+ return EconomicMapImpl.create(strategy, c, true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Equivalence.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT},
+ * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}.
+ *
+ * @since 1.0
+ */
+public abstract class Equivalence {
+
+ /**
+ * Default equivalence calling {@link #equals(Object)} 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
+ */
+ public static final Equivalence DEFAULT = new Equivalence() {
+
+ @Override
+ public boolean equals(Object a, Object b) {
+ return a.equals(b);
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return o.hashCode();
+ }
+ };
+
+ /**
+ * 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
+ */
+ public static final Equivalence IDENTITY = new Equivalence() {
+
+ @Override
+ public boolean equals(Object a, Object b) {
+ return a == b;
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return o.hashCode();
+ }
+ };
+
+ /**
+ * Identity equivalence using {@code ==} to check equality and
+ * {@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
+ */
+ public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() {
+
+ @Override
+ public boolean equals(Object a, Object b) {
+ return a == b;
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ return System.identityHashCode(o);
+ }
+ };
+
+ /**
+ * Subclass for creating custom equivalence definitions.
+ *
+ * @since 1.0
+ */
+ protected Equivalence() {
+ }
+
+ /**
+ * Returns {@code true} if the non-{@code null} arguments are equal to each other and
+ * {@code false} otherwise.
+ *
+ * @since 1.0
+ */
+ public abstract boolean equals(Object a, Object b);
+
+ /**
+ * Returns the hash code of a non-{@code null} argument {@code o}.
+ *
+ * @since 1.0
+ */
+ public abstract int hashCode(Object o);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/MapCursor.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Cursor to iterate over a mutable map.
+ *
+ * @since 1.0
+ */
+public interface MapCursor<K, V> extends UnmodifiableMapCursor<K, V> {
+ /**
+ * Remove the current entry from the map. May only be called once. After calling
+ * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on
+ * the current entry.
+ *
+ * @since 1.0
+ */
+ void remove();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Pair.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Objects;
+
+/**
+ * Utility class representing a pair of values.
+ *
+ * @since 1.0
+ */
+public final class Pair<L, R> {
+
+ private static final Pair<Object, Object> EMPTY = new Pair<>(null, null);
+
+ private final L left;
+ private final R right;
+
+ /**
+ * Returns an empty pair.
+ *
+ * @since 1.0
+ */
+ @SuppressWarnings("unchecked")
+ public static <L, R> Pair<L, R> empty() {
+ return (Pair<L, R>) EMPTY;
+ }
+
+ /**
+ * Constructs a pair with its left value being {@code left}, or returns an empty pair if
+ * {@code left} is null.
+ *
+ * @return the constructed pair or an empty pair if {@code left} is null.
+ * @since 1.0
+ */
+ public static <L, R> Pair<L, R> createLeft(L left) {
+ if (left == null) {
+ return empty();
+ } else {
+ return new Pair<>(left, null);
+ }
+ }
+
+ /**
+ * Constructs a pair with its right value being {@code right}, or returns an empty pair if
+ * {@code right} is null.
+ *
+ * @return the constructed pair or an empty pair if {@code right} is null.
+ * @since 1.0
+ */
+ public static <L, R> Pair<L, R> createRight(R right) {
+ if (right == null) {
+ return empty();
+ } else {
+ return new Pair<>(null, right);
+ }
+ }
+
+ /**
+ * Constructs a pair with its left value being {@code left}, and its right value being
+ * {@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
+ */
+ public static <L, R> Pair<L, R> create(L left, R right) {
+ if (right == null && left == null) {
+ return empty();
+ } else {
+ return new Pair<>(left, right);
+ }
+ }
+
+ private Pair(L left, R right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ /**
+ * Returns the left value of this pair.
+ *
+ * @since 1.0
+ */
+ public L getLeft() {
+ return left;
+ }
+
+ /**
+ * Returns the right value of this pair.
+ *
+ * @since 1.0
+ */
+ public R getRight() {
+ return right;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.0
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(left) + 31 * Objects.hashCode(right);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.0
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof Pair) {
+ Pair<L, R> pair = (Pair<L, R>) obj;
+ return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.0
+ */
+ @Override
+ public String toString() {
+ return String.format("(%s, %s)", left, right);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicMap.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Unmodifiable memory efficient map data structure.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableEconomicMap<K, V> {
+
+ /**
+ * Returns the value to which {@code key} is mapped, or {@code null} if this map contains no
+ * mapping for {@code key}.
+ *
+ * @since 1.0
+ */
+ V get(K key);
+
+ /**
+ * Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map
+ * contains no mapping for {@code key}.
+ *
+ * @since 1.0
+ */
+ default V get(K key, V defaultValue) {
+ V v = get(key);
+ if (v == null) {
+ return defaultValue;
+ }
+ return v;
+ }
+
+ /**
+ * Returns {@code true} if this map contains a mapping for {@code key}.
+ *
+ * @since 1.0
+ */
+ boolean containsKey(K key);
+
+ /**
+ * Returns the number of key-value mappings in this map.
+ *
+ * @since 1.0
+ */
+ int size();
+
+ /**
+ * Returns {@code true} if this map contains no key-value mappings.
+ *
+ * @since 1.0
+ */
+ boolean isEmpty();
+
+ /**
+ * Returns a {@link Iterable} view of the values contained in this map.
+ *
+ * @since 1.0
+ */
+ Iterable<V> getValues();
+
+ /**
+ * Returns a {@link Iterable} view of the keys contained in this map.
+ *
+ * @since 1.0
+ */
+ Iterable<K> getKeys();
+
+ /**
+ * Returns a {@link UnmodifiableMapCursor} view of the mappings contained in this map.
+ *
+ * @since 1.0
+ */
+ UnmodifiableMapCursor<K, V> getEntries();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicSet.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Unmodifiable memory efficient set data structure.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableEconomicSet<E> extends Iterable<E> {
+
+ /**
+ * Returns {@code true} if this set contains a mapping for the {@code element}.
+ *
+ * @since 1.0
+ */
+ boolean contains(E element);
+
+ /**
+ * Returns the number of elements in this set.
+ *
+ * @since 1.0
+ */
+ int size();
+
+ /**
+ * Returns {@code true} if this set contains no elements.
+ *
+ * @since 1.0
+ */
+ boolean isEmpty();
+
+ /**
+ * Stores all of the elements in this set into {@code target}. An
+ * {@link UnsupportedOperationException} will be thrown if the length of {@code target} does not
+ * match the size of this set.
+ *
+ * @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
+ */
+ default E[] toArray(E[] target) {
+ if (target.length != size()) {
+ throw new UnsupportedOperationException("Length of target array must equal the size of the set.");
+ }
+
+ int index = 0;
+ for (E element : this) {
+ target[index++] = element;
+ }
+
+ return target;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableMapCursor.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Cursor to iterate over a map without changing its contents.
+ *
+ * @since 1.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
+ */
+ boolean advance();
+
+ /**
+ * The key of the current entry.
+ *
+ * @since 1.0
+ */
+ K getKey();
+
+ /**
+ * The value of the current entry.
+ *
+ * @since 1.0
+ */
+ V getValue();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ @ApiInfo(
+ group="Graal SDK"
+ )
+ */
+/**
+ * The Graal-SDK collections package contains memory efficient data structures.
+ *
+ * @see jdk.internal.vm.compiler.collections.EconomicMap
+ * @see jdk.internal.vm.compiler.collections.EconomicSet
+ *
+ * @since 1.0
+ */
+package jdk.internal.vm.compiler.collections;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/ComparableWord.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+/**
+ * A machine-word-sized value that can be compared for equality.
+ *
+ * @since 1.0
+ */
+public interface ComparableWord extends WordBase {
+
+ /**
+ * Compares this word with the specified value.
+ *
+ * @param val value to which this word is to be compared.
+ * @return {@code this == val}
+ *
+ * @since 1.0
+ */
+ boolean equal(ComparableWord val);
+
+ /**
+ * Compares this word with the specified value.
+ *
+ * @param val value to which this word is to be compared.
+ * @return {@code this != val}
+ *
+ * @since 1.0
+ */
+ boolean notEqual(ComparableWord val);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/LocationIdentity.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+// JaCoCo Exclude
+
+/**
+ * Marker interface for location identities. A different location identity of two memory accesses
+ * guarantees that the two accesses do not interfere.
+ * <p>
+ * Clients of {@link LocationIdentity} must use {@link #equals(Object)}, not {@code ==}, when
+ * 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
+ */
+public abstract class LocationIdentity {
+
+ private static final class AnyLocationIdentity extends LocationIdentity {
+ @Override
+ public boolean isImmutable() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "ANY_LOCATION";
+ }
+ }
+
+ private static final class InitLocationIdentity extends LocationIdentity {
+ @Override
+ public boolean isImmutable() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "INIT_LOCATION";
+ }
+ }
+
+ /**
+ * Creates a new location identity. Subclasses are responsible to provide proper implementations
+ * of {@link #equals} and {@link #hashCode}.
+ *
+ * @since 1.0
+ */
+ protected LocationIdentity() {
+ }
+
+ /**
+ * Indicates that the given location is the union of all possible mutable locations. A write to
+ * 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
+ */
+ public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity();
+
+ /**
+ * Location only allowed to be used for writes. Indicates that a completely new memory location
+ * 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
+ */
+ public static final LocationIdentity INIT_LOCATION = new InitLocationIdentity();
+
+ /**
+ * Indicates that the given location is the union of all possible mutable locations. A write to
+ * 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
+ */
+ public static LocationIdentity any() {
+ return ANY_LOCATION;
+ }
+
+ /**
+ * Location only allowed to be used for writes. Indicates that a completely new memory location
+ * 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
+ */
+ public static LocationIdentity init() {
+ return INIT_LOCATION;
+ }
+
+ /**
+ * 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
+ */
+ public abstract boolean isImmutable();
+
+ /**
+ * The inversion of {@link #isImmutable}.
+ *
+ * @since 1.0
+ */
+ public final boolean isMutable() {
+ return !isImmutable();
+ }
+
+ /**
+ * Returns true if this location identity is {@link #any}.
+ *
+ * @since 1.0
+ */
+ public final boolean isAny() {
+ return this == ANY_LOCATION;
+ }
+
+ /**
+ * Returns true if this location identity is {@link #init}.
+ *
+ * @since 1.0
+ */
+ public final boolean isInit() {
+ return this == INIT_LOCATION;
+ }
+
+ /**
+ * Returns true if this location identity is not {@link #any}.
+ *
+ * @since 1.0
+ */
+ public final boolean isSingle() {
+ return this != ANY_LOCATION;
+ }
+
+ /**
+ * Returns true if the memory slice denoted by this location identity may overlap with the
+ * provided other location identity.
+ *
+ * @since 1.0
+ */
+ public final boolean overlaps(LocationIdentity other) {
+ return isAny() || other.isAny() || this.equals(other);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/Pointer.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,1415 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+/**
+ * Lowest-level memory access of native C memory.
+ * <p>
+ * Do not use these methods to access Java objects. These methods access the raw memory without any
+ * null checks, read- or write barriers. Even when the VM uses compressed pointers, then readObject
+ * and writeObject methods access uncompressed pointers.
+ *
+ * @since 1.0
+ */
+public interface Pointer extends UnsignedWord, PointerBase {
+
+ /**
+ * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
+ * checks are performed. The caller must ensure that the Pointer contains a valid Java object
+ * that can i.e., processed by the garbage collector.
+ *
+ * @return this Pointer cast to Object.
+ *
+ * @since 1.0
+ */
+ Object toObject();
+
+ /**
+ * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
+ * checks are performed. The caller must ensure that the Pointer contains a valid Java object
+ * that can i.e., processed by the garbage collector and the Pointer does not contain 0.
+ *
+ * @return this Pointer cast to non-null Object.
+ *
+ * @since 1.0
+ */
+ Object toObjectNonNull();
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ byte readByte(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ char readChar(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ short readShort(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ int readInt(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ long readLong(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ float readFloat(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ double readDouble(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ <T extends WordBase> T readWord(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ Object readObject(WordBase offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ byte readByte(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ char readChar(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ short readShort(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ int readInt(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ long readLong(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ float readFloat(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ double readDouble(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ <T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the read
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ Object readObject(int offset, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeChar(WordBase offset, char val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeShort(WordBase offset, short val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeInt(WordBase offset, int val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeLong(WordBase offset, long val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
+
+ /**
+ * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
+ * are in bytes. The memory must be uninitialized or zero prior to this operation.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeByte(int offset, byte val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeChar(int offset, char val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeShort(int offset, short val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeInt(int offset, int val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeLong(int offset, long val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeFloat(int offset, float val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeDouble(int offset, double val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
+
+ /**
+ * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
+ * are in bytes. The memory must be uninitialized or zero prior to this operation.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void initializeLong(int offset, long val, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param locationIdentity the identity of the write
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeObject(int offset, Object val, LocationIdentity locationIdentity);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ byte readByte(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ char readChar(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ short readShort(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ int readInt(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ long readLong(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ float readFloat(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ double readDouble(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ <T extends WordBase> T readWord(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ Object readObject(WordBase offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ byte readByte(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ char readChar(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ short readShort(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ int readInt(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ long readLong(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ float readFloat(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ double readDouble(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ <T extends WordBase> T readWord(int offset);
+
+ /**
+ * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @return the result of the memory access
+ *
+ * @since 1.0
+ */
+ Object readObject(int offset);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeByte(WordBase offset, byte val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeChar(WordBase offset, char val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeShort(WordBase offset, short val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeInt(WordBase offset, int val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeLong(WordBase offset, long val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeFloat(WordBase offset, float val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeDouble(WordBase offset, double val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeWord(WordBase offset, WordBase val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeObject(WordBase offset, Object val);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ int compareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ <T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapWord(WordBase offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ * <p>
+ * The offset is always treated as a {@link SignedWord} value. However, the static type is
+ * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
+ * knows that the highest-order bit of the unsigned value is never used).
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeByte(int offset, byte val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeChar(int offset, char val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeShort(int offset, short val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeInt(int offset, int val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeLong(int offset, long val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeFloat(int offset, float val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeDouble(int offset, double val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeWord(int offset, WordBase val);
+
+ /**
+ * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+ * bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param val the value to be written to memory
+ *
+ * @since 1.0
+ */
+ void writeObject(int offset, Object val);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ <T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return The value after the atomic exchange
+ *
+ * @since 1.0
+ */
+ Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
+
+ /**
+ * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+ * offset are in bytes.
+ *
+ * @param offset the signed offset for the memory access
+ * @param expectedValue the expected value of the atomic exchange
+ * @param newValue the new value of the atomic exchange
+ * @param locationIdentity the identity of the memory location
+ * @return {@code true} if successful. False return indicates that the actual value was not
+ * equal to the expected value.
+ *
+ * @since 1.0
+ */
+ boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+ // Math functions that are defined in Unsigned, but known to preserve the
+ // pointer-characteristics.
+ // It is therefore safe that they return a static type of Pointer instead of Unsigned.
+
+ /**
+ * Returns a Pointer whose value is {@code (this + val)}.
+ *
+ * @param val value to be added to this Pointer.
+ * @return {@code this + val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer add(UnsignedWord val);
+
+ /**
+ * Returns a Pointer whose value is {@code (this + val)}.
+ *
+ * @param val value to be added to this Pointer.
+ * @return {@code this + val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer add(int val);
+
+ /**
+ * Returns a Pointer whose value is {@code (this - val)}.
+ *
+ * @param val value to be subtracted from this Pointer.
+ * @return {@code this - val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer subtract(UnsignedWord val);
+
+ /**
+ * Returns a Pointer whose value is {@code (this - val)}.
+ *
+ * @param val value to be subtracted from this Pointer.
+ * @return {@code this - val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer subtract(int val);
+
+ /**
+ * Returns a Pointer whose value is {@code (this & val)}.
+ *
+ * @param val value to be AND'ed with this Pointer.
+ * @return {@code this & val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer and(UnsignedWord val);
+
+ /**
+ * Returns a Pointer whose value is {@code (this & val)}.
+ *
+ * @param val value to be AND'ed with this Pointer.
+ * @return {@code this & val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer and(int val);
+
+ /**
+ * Returns a Pointer whose value is {@code (this | val)}.
+ *
+ * @param val value to be OR'ed with this Pointer.
+ * @return {@code this | val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer or(UnsignedWord val);
+
+ /**
+ * Returns a Pointer whose value is {@code (this | val)}.
+ *
+ * @param val value to be OR'ed with this Pointer.
+ * @return {@code this | val}
+ *
+ * @since 1.0
+ */
+ @Override
+ Pointer or(int val);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/PointerBase.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+/**
+ * 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
+ */
+public interface PointerBase extends ComparableWord {
+
+ /**
+ * Returns true if this pointer is the {@link WordFactory#nullPointer null pointer}.
+ *
+ * @since 1.0
+ */
+ boolean isNull();
+
+ /**
+ * Returns true if this pointer is not the {@link WordFactory#nullPointer null pointer}.
+ *
+ * @since 1.0
+ */
+ boolean isNonNull();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/SignedWord.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+/**
+ * Represents a signed word-sized value.
+ *
+ * @since 1.0
+ */
+public interface SignedWord extends ComparableWord {
+
+ /**
+ * Returns a Signed whose value is {@code (this + val)}.
+ *
+ * @param val value to be added to this Signed.
+ * @return {@code this + val}
+ *
+ * @since 1.0
+ */
+ SignedWord add(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this - val)}.
+ *
+ * @param val value to be subtracted from this Signed.
+ * @return {@code this - val}
+ *
+ * @since 1.0
+ */
+ SignedWord subtract(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this * val)}.
+ *
+ * @param val value to be multiplied by this Signed.
+ * @return {@code this * val}
+ *
+ * @since 1.0
+ */
+ SignedWord multiply(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this / val)}.
+ *
+ * @param val value by which this Signed is to be divided.
+ * @return {@code this / val}
+ *
+ * @since 1.0
+ */
+ SignedWord signedDivide(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this % val)}.
+ *
+ * @param val value by which this Signed is to be divided, and the remainder computed.
+ * @return {@code this % val}
+ *
+ * @since 1.0
+ */
+ SignedWord signedRemainder(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this << n)}.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this << n}
+ *
+ * @since 1.0
+ */
+ SignedWord shiftLeft(UnsignedWord n);
+
+ /**
+ * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this >> n}
+ *
+ * @since 1.0
+ */
+ SignedWord signedShiftRight(UnsignedWord n);
+
+ /**
+ * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
+ * if and only if this and val are both negative.)
+ *
+ * @param val value to be AND'ed with this Signed.
+ * @return {@code this & val}
+ *
+ * @since 1.0
+ */
+ SignedWord and(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
+ * if and only if either this or val is negative.)
+ *
+ * @param val value to be OR'ed with this Signed.
+ * @return {@code this | val}
+ *
+ * @since 1.0
+ */
+ SignedWord or(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
+ * if and only if exactly one of this and val are negative.)
+ *
+ * @param val value to be XOR'ed with this Signed.
+ * @return {@code this ^ val}
+ *
+ * @since 1.0
+ */
+ SignedWord xor(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (~this)}. (This method returns a negative value if and
+ * only if this Signed is non-negative.)
+ *
+ * @return {@code ~this}
+ *
+ * @since 1.0
+ */
+ SignedWord not();
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this == val}
+ *
+ * @since 1.0
+ */
+ boolean equal(SignedWord val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this != val}
+ *
+ * @since 1.0
+ */
+ boolean notEqual(SignedWord val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this < val}
+ *
+ * @since 1.0
+ */
+ boolean lessThan(SignedWord val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this <= val}
+ *
+ * @since 1.0
+ */
+ boolean lessOrEqual(SignedWord val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this > val}
+ *
+ * @since 1.0
+ */
+ boolean greaterThan(SignedWord val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this >= val}
+ *
+ * @since 1.0
+ */
+ boolean greaterOrEqual(SignedWord val);
+
+ /**
+ * Returns a Signed whose value is {@code (this + val)}.
+ *
+ * @param val value to be added to this Signed.
+ * @return {@code this + val}
+ *
+ * @since 1.0
+ */
+ SignedWord add(int val);
+
+ /**
+ * Returns a Signed whose value is {@code (this - val)}.
+ *
+ * @param val value to be subtracted from this Signed.
+ * @return {@code this - val}
+ *
+ * @since 1.0
+ */
+ SignedWord subtract(int val);
+
+ /**
+ * Returns a Signed whose value is {@code (this * val)}.
+ *
+ * @param val value to be multiplied by this Signed.
+ * @return {@code this * val}
+ *
+ * @since 1.0
+ */
+ SignedWord multiply(int val);
+
+ /**
+ * Returns a Signed whose value is {@code (this / val)}.
+ *
+ * @param val value by which this Signed is to be divided.
+ * @return {@code this / val}
+ *
+ * @since 1.0
+ */
+ SignedWord signedDivide(int val);
+
+ /**
+ * Returns a Signed whose value is {@code (this % val)}.
+ *
+ * @param val value by which this Signed is to be divided, and the remainder computed.
+ * @return {@code this % val}
+ *
+ * @since 1.0
+ */
+ SignedWord signedRemainder(int val);
+
+ /**
+ * Returns a Signed whose value is {@code (this << n)}.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this << n}
+ *
+ * @since 1.0
+ */
+ SignedWord shiftLeft(int n);
+
+ /**
+ * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this >> n}
+ *
+ * @since 1.0
+ */
+ SignedWord signedShiftRight(int n);
+
+ /**
+ * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
+ * if and only if this and val are both negative.)
+ *
+ * @param val value to be AND'ed with this Signed.
+ * @return {@code this & val}
+ *
+ * @since 1.0
+ */
+ SignedWord and(int val);
+
+ /**
+ * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
+ * if and only if either this or val is negative.)
+ *
+ * @param val value to be OR'ed with this Signed.
+ * @return {@code this | val}
+ *
+ * @since 1.0
+ */
+ SignedWord or(int val);
+
+ /**
+ * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
+ * if and only if exactly one of this and val are negative.)
+ *
+ * @param val value to be XOR'ed with this Signed.
+ * @return {@code this ^ val}
+ *
+ * @since 1.0
+ */
+ SignedWord xor(int val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this == val}
+ *
+ * @since 1.0
+ */
+ boolean equal(int val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this != val}
+ *
+ * @since 1.0
+ */
+ boolean notEqual(int val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this < val}
+ *
+ * @since 1.0
+ */
+ boolean lessThan(int val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this <= val}
+ *
+ * @since 1.0
+ */
+ boolean lessOrEqual(int val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this > val}
+ *
+ * @since 1.0
+ */
+ boolean greaterThan(int val);
+
+ /**
+ * Compares this Signed with the specified value.
+ *
+ * @param val value to which this Signed is to be compared.
+ * @return {@code this >= val}
+ *
+ * @since 1.0
+ */
+ boolean greaterOrEqual(int val);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/UnsignedWord.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+/**
+ * Represents an unsigned word-sized value.
+ *
+ * @since 1.0
+ */
+public interface UnsignedWord extends ComparableWord {
+
+ /**
+ * Returns a Unsigned whose value is {@code (this + val)}.
+ *
+ * @param val value to be added to this Unsigned.
+ * @return {@code this + val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord add(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this - val)}.
+ *
+ * @param val value to be subtracted from this Unsigned.
+ * @return {@code this - val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord subtract(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this * val)}.
+ *
+ * @param val value to be multiplied by this Unsigned.
+ * @return {@code this * val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord multiply(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this / val)}.
+ *
+ * @param val value by which this Unsigned is to be divided.
+ * @return {@code this / val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord unsignedDivide(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this % val)}.
+ *
+ * @param val value by which this Unsigned is to be divided, and the remainder computed.
+ * @return {@code this % val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord unsignedRemainder(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this << n)}.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this << n}
+ *
+ * @since 1.0
+ */
+ UnsignedWord shiftLeft(UnsignedWord n);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this >> n}
+ *
+ * @since 1.0
+ */
+ UnsignedWord unsignedShiftRight(UnsignedWord n);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this & val)}.
+ *
+ * @param val value to be AND'ed with this Unsigned.
+ * @return {@code this & val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord and(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this | val)}.
+ *
+ * @param val value to be OR'ed with this Unsigned.
+ * @return {@code this | val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord or(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this ^ val)}.
+ *
+ * @param val value to be XOR'ed with this Unsigned.
+ * @return {@code this ^ val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord xor(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (~this)}.
+ *
+ * @return {@code ~this}
+ *
+ * @since 1.0
+ */
+ UnsignedWord not();
+
+ /**
+ * Compares this Unsigned with the specified value.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this == val}
+ *
+ * @since 1.0
+ */
+ boolean equal(UnsignedWord val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this != val}
+ *
+ * @since 1.0
+ */
+ boolean notEqual(UnsignedWord val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this < val}
+ *
+ * @since 1.0
+ */
+ boolean belowThan(UnsignedWord val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this <= val}
+ *
+ * @since 1.0
+ */
+ boolean belowOrEqual(UnsignedWord val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this > val}
+ *
+ * @since 1.0
+ */
+ boolean aboveThan(UnsignedWord val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this >= val}
+ *
+ * @since 1.0
+ */
+ boolean aboveOrEqual(UnsignedWord val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this + val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to be added to this Unsigned.
+ * @return {@code this + val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord add(int val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this - val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to be subtracted from this Unsigned.
+ * @return {@code this - val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord subtract(int val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this * val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to be multiplied by this Unsigned.
+ * @return {@code this * val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord multiply(int val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this / val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value by which this Unsigned is to be divided.
+ * @return {@code this / val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord unsignedDivide(int val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this % val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value by which this Unsigned is to be divided, and the remainder computed.
+ * @return {@code this % val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord unsignedRemainder(int val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this << n)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this << n}
+ *
+ * @since 1.0
+ */
+ UnsignedWord shiftLeft(int n);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param n shift distance, in bits.
+ * @return {@code this >> n}
+ *
+ * @since 1.0
+ */
+ UnsignedWord unsignedShiftRight(int n);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this & val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to be AND'ed with this Unsigned.
+ * @return {@code this & val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord and(int val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this | val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to be OR'ed with this Unsigned.
+ * @return {@code this | val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord or(int val);
+
+ /**
+ * Returns a Unsigned whose value is {@code (this ^ val)}.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to be XOR'ed with this Unsigned.
+ * @return {@code this ^ val}
+ *
+ * @since 1.0
+ */
+ UnsignedWord xor(int val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this == val}
+ *
+ * @since 1.0
+ */
+ boolean equal(int val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this != val}
+ *
+ * @since 1.0
+ */
+ boolean notEqual(int val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this < val}
+ *
+ * @since 1.0
+ */
+ boolean belowThan(int val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this <= val}
+ *
+ * @since 1.0
+ */
+ boolean belowOrEqual(int val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this > val}
+ *
+ * @since 1.0
+ */
+ boolean aboveThan(int val);
+
+ /**
+ * Compares this Unsigned with the specified value.
+ * <p>
+ * Note that the right operand is a signed value, while the operation is performed unsigned.
+ * Therefore, the result is only well-defined for positive right operands.
+ *
+ * @param val value to which this Unsigned is to be compared.
+ * @return {@code this >= val}
+ *
+ * @since 1.0
+ */
+ boolean aboveOrEqual(int val);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordBase.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+/**
+ * The root of the interface hierarchy for machine-word-sized values.
+ *
+ * @since 1.0
+ */
+public interface WordBase {
+
+ /**
+ * Conversion to a Java primitive value.
+ *
+ * @since 1.0
+ */
+ long rawValue();
+
+ /**
+ * This is deprecated because of the easy to mistype name collision between {@link #equals} and
+ * the other word based equality routines. In general you should never be statically calling
+ * this method anyway.
+ *
+ * @since 1.0
+ */
+ @Override
+ @Deprecated
+ boolean equals(Object o);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word;
+
+import jdk.internal.vm.compiler.word.impl.WordBoxFactory;
+import jdk.internal.vm.compiler.word.impl.WordFactoryOpcode;
+import jdk.internal.vm.compiler.word.impl.WordFactoryOperation;
+
+/**
+ * Provides factory method to create machine-word-sized values.
+ *
+ * @since 1.0
+ */
+public final class WordFactory {
+
+ private WordFactory() {
+ }
+
+ /**
+ * The constant 0, i.e., the word with no bits set. There is no difference between a signed and
+ * unsigned zero.
+ *
+ * @return the constant 0.
+ *
+ * @since 1.0
+ */
+ @WordFactoryOperation(opcode = WordFactoryOpcode.ZERO)
+ public static <T extends WordBase> T zero() {
+ return WordBoxFactory.box(0L);
+ }
+
+ /**
+ * The null pointer, i.e., the pointer with no bits set. There is no difference to a signed or
+ * unsigned {@link #zero}.
+ *
+ * @return the null pointer.
+ *
+ * @since 1.0
+ */
+ @WordFactoryOperation(opcode = WordFactoryOpcode.ZERO)
+ public static <T extends PointerBase> T nullPointer() {
+ return WordBoxFactory.box(0L);
+ }
+
+ /**
+ * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned
+ * 64-bit value (in contrast to the semantics of a Java long).
+ *
+ * @param val a 64 bit unsigned value
+ * @return the value cast to Word
+ *
+ * @since 1.0
+ */
+ @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
+ public static <T extends UnsignedWord> T unsigned(long val) {
+ return WordBoxFactory.box(val);
+ }
+
+ /**
+ * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is
+ * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
+ *
+ * @param val a 64 bit unsigned value
+ * @return the value cast to PointerBase
+ *
+ * @since 1.0
+ */
+ @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
+ public static <T extends PointerBase> T pointer(long val) {
+ return WordBoxFactory.box(val);
+ }
+
+ /**
+ * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned
+ * 32-bit value (in contrast to the semantics of a Java int).
+ *
+ * @param val a 32 bit unsigned value
+ * @return the value cast to Word
+ *
+ * @since 1.0
+ */
+ @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
+ public static <T extends UnsignedWord> T unsigned(int val) {
+ return WordBoxFactory.box(val & 0xffffffffL);
+ }
+
+ /**
+ * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed
+ * 64-bit value (unchanged semantics of a Java long).
+ *
+ * @param val a 64 bit signed value
+ * @return the value cast to Word
+ *
+ * @since 1.0
+ */
+ @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_SIGNED)
+ public static <T extends SignedWord> T signed(long val) {
+ return WordBoxFactory.box(val);
+ }
+
+ /**
+ * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed
+ * 32-bit value (unchanged semantics of a Java int).
+ *
+ * @param val a 32 bit signed value
+ * @return the value cast to Word
+ *
+ * @since 1.0
+ */
+ @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_SIGNED)
+ public static <T extends SignedWord> T signed(int val) {
+ return WordBoxFactory.box(val);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/impl/WordBoxFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,42 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word.impl;
+
+import jdk.internal.vm.compiler.word.WordBase;
+
+/**
+ * Base class for a factory to create boxed {@link Word} instances. A concrete subclass must
+ * initialize {@link #boxFactory}.
+ */
+public abstract class WordBoxFactory {
+
+ protected static WordBoxFactory boxFactory;
+
+ protected abstract <T extends WordBase> T boxImpl(long val);
+
+ public static <T extends WordBase> T box(long val) {
+ return boxFactory.boxImpl(val);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/impl/WordFactoryOpcode.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word.impl;
+
+/**
+ * The canonical {@link WordFactoryOperation} represented by a method in a word type.
+ */
+public enum WordFactoryOpcode {
+ ZERO,
+ FROM_UNSIGNED,
+ FROM_SIGNED,
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/impl/WordFactoryOperation.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.word.impl;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Links a method to a canonical operation represented by an {@link WordFactoryOpcode} val.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface WordFactoryOperation {
+ WordFactoryOpcode opcode();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ @ApiInfo(
+ group="Graal SDK"
+ )
+ */
+/**
+ * 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
+ */
+package jdk.internal.vm.compiler.word;
\ No newline at end of file
--- a/src/jdk.internal.vm.compiler/share/classes/module-info.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/module-info.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,9 +36,10 @@
uses org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
uses org.graalvm.compiler.hotspot.HotSpotBackendFactory;
uses org.graalvm.compiler.hotspot.HotSpotCodeCacheListener;
- uses org.graalvm.compiler.options.OptionValuesAccess;
+ uses org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
+ exports jdk.internal.vm.compiler.collections to jdk.internal.vm.compiler.management;
exports org.graalvm.compiler.api.directives to jdk.aot;
exports org.graalvm.compiler.api.runtime to jdk.aot;
exports org.graalvm.compiler.api.replacements to jdk.aot;
@@ -46,9 +47,13 @@
exports org.graalvm.compiler.bytecode to jdk.aot;
exports org.graalvm.compiler.code to jdk.aot;
exports org.graalvm.compiler.core to jdk.aot;
- exports org.graalvm.compiler.core.common to jdk.aot;
+ exports org.graalvm.compiler.core.common to
+ jdk.aot,
+ jdk.internal.vm.compiler.management;
exports org.graalvm.compiler.core.target to jdk.aot;
- exports org.graalvm.compiler.debug to jdk.aot;
+ exports org.graalvm.compiler.debug to
+ jdk.aot,
+ jdk.internal.vm.compiler.management;
exports org.graalvm.compiler.graph to jdk.aot;
exports org.graalvm.compiler.hotspot to
jdk.aot,
@@ -62,12 +67,17 @@
exports org.graalvm.compiler.lir.phases to jdk.aot;
exports org.graalvm.compiler.nodes to jdk.aot;
exports org.graalvm.compiler.nodes.graphbuilderconf to jdk.aot;
- exports org.graalvm.compiler.options to jdk.aot;
+ exports org.graalvm.compiler.options to
+ jdk.aot,
+ jdk.internal.vm.compiler.management;
exports org.graalvm.compiler.phases to jdk.aot;
exports org.graalvm.compiler.phases.tiers to jdk.aot;
exports org.graalvm.compiler.printer to jdk.aot;
exports org.graalvm.compiler.runtime to jdk.aot;
exports org.graalvm.compiler.replacements to jdk.aot;
+ exports org.graalvm.compiler.serviceprovider to
+ jdk.aot,
+ jdk.internal.vm.compiler.management;
exports org.graalvm.compiler.word to jdk.aot;
- exports org.graalvm.word to jdk.aot;
+ exports jdk.internal.vm.compiler.word to jdk.aot;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicSet;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EconomicMapImplTest {
-
- @Test(expected = UnsupportedOperationException.class)
- public void testRemoveNull() {
- EconomicMap<Integer, Integer> map = EconomicMap.create(10);
- map.removeKey(null);
- }
-
- @Test
- public void testInitFromHashSet() {
- UnmodifiableEconomicSet<Integer> set = new UnmodifiableEconomicSet<Integer>() {
-
- @Override
- public boolean contains(Integer element) {
- return element == 0;
- }
-
- @Override
- public int size() {
- return 1;
- }
-
- @Override
- public boolean isEmpty() {
- return false;
- }
-
- @Override
- public Iterator<Integer> iterator() {
- return new Iterator<Integer>() {
-
- private boolean visited = false;
-
- @Override
- public boolean hasNext() {
- return !visited;
- }
-
- @Override
- public Integer next() {
- if (visited) {
- return null;
- } else {
- visited = true;
- return 1;
- }
- }
- };
- }
- };
-
- EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.DEFAULT, set);
- Assert.assertEquals(newSet.size(), 1);
- }
-
- @Test
- public void testCopyHash() {
- EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
- set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
- EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.IDENTITY, set);
- Assert.assertEquals(newSet.size(), 10);
- newSet.remove(8);
- newSet.remove(9);
- Assert.assertEquals(newSet.size(), 8);
- }
-
- @Test
- public void testNewEquivalence() {
- EconomicSet<Integer> set = EconomicSet.create(new Equivalence() {
- @Override
- public boolean equals(Object a, Object b) {
- return false;
- }
-
- @Override
- public int hashCode(Object o) {
- return 0;
- }
- });
- set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
- Assert.assertTrue(set.add(new Integer(0)));
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testMapPutNull() {
- EconomicMap<Integer, Integer> map = EconomicMap.create();
- map.put(null, null);
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Objects;
-import java.util.Random;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.UnmodifiableMapCursor;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class EconomicMapLargeTest {
-
- @Parameter(value = 0) public EconomicMap<Object, Object> testMap;
- @Parameter(value = 1) public EconomicMap<Object, Object> referenceMap;
- @Parameter(value = 2) public String name;
-
- @Parameters(name = "{2}")
- public static Collection<Object[]> data() {
- return Arrays.asList(new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.create(Equivalence.DEFAULT), "EconomicMap"},
- new Object[]{EconomicMap.create(Equivalence.IDENTITY), EconomicMap.create(Equivalence.IDENTITY), "EconomicMap(IDENTITY)"},
- new Object[]{EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE), EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE),
- "EconomicMap(IDENTITY_WITH_SYSTEM_HASHCODE)"},
- new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.wrapMap(new LinkedHashMap<>()), "EconomicMap<->wrapMap"},
- new Object[]{EconomicMap.wrapMap(new LinkedHashMap<>()), EconomicMap.wrapMap(new LinkedHashMap<>()), "wrapMap"});
- }
-
- private static int[] createRandomRange(Random random, int count) {
- int[] result = new int[count];
- for (int i = 0; i < count; ++i) {
- int range = random.nextInt(14);
- if (range == 0 || range > 10) {
- range = Integer.MAX_VALUE;
- } else if (range == 10) {
- range = 100;
- }
- result[i] = range;
- }
- return result;
- }
-
- private static final class BadHashClass {
- private int value;
-
- BadHashClass(int randomInt) {
- this.value = randomInt;
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof BadHashClass) {
- BadHashClass badHashClass = (BadHashClass) other;
- return badHashClass.value == value;
- }
- return false;
- }
- }
-
- interface MapAction {
- Object perform(EconomicMap<Object, Object> map, int randomInt);
- }
-
- static final Object EXISTING_VALUE = new Object();
-
- static final MapAction[] INCREASE_ACTIONS = new MapAction[]{
- (map, randomInt) -> map.put(randomInt, "value"),
- (map, randomInt) -> map.get(randomInt)
- };
-
- static final MapAction[] ACTIONS = new MapAction[]{
- (map, randomInt) -> map.removeKey(randomInt),
- (map, randomInt) -> map.put(randomInt, "value"),
- (map, randomInt) -> map.put(randomInt, null),
- (map, randomInt) -> map.put(EXISTING_VALUE, randomInt),
- (map, randomInt) -> {
- if (randomInt == 0) {
- map.clear();
- }
- return map.isEmpty();
- },
- (map, randomInt) -> map.containsKey(randomInt),
- (map, randomInt) -> map.get(randomInt),
- (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"),
- (map, randomInt) -> {
- if (randomInt == 0) {
- map.replaceAll((key, value) -> Objects.toString(value) + "!");
- }
- return map.isEmpty();
- }
-
- };
-
- @Test
- public void testVeryLarge() {
- testMap.clear();
- referenceMap.clear();
-
- Random random = new Random(0);
- for (int i = 0; i < 200000; ++i) {
- for (int j = 0; j < INCREASE_ACTIONS.length; ++j) {
- int nextInt = random.nextInt(10000000);
- MapAction action = INCREASE_ACTIONS[j];
- Object result = action.perform(testMap, nextInt);
- Object referenceResult = action.perform(referenceMap, nextInt);
- Assert.assertEquals(result, referenceResult);
- }
- }
- }
-
- /**
- * Tests a sequence of random operations on the map.
- */
- @Test
- public void testAddRemove() {
- testMap.clear();
- referenceMap.clear();
-
- for (int seed = 0; seed < 10; ++seed) {
- Random random = new Random(seed);
- int[] ranges = createRandomRange(random, ACTIONS.length);
- int value = random.nextInt(10000);
- for (int i = 0; i < value; ++i) {
- for (int j = 0; j < ACTIONS.length; ++j) {
- if (random.nextInt(ranges[j]) == 0) {
- int nextInt = random.nextInt(100);
- MapAction action = ACTIONS[j];
- Object result = action.perform(testMap, nextInt);
- Object referenceResult = action.perform(referenceMap, nextInt);
- Assert.assertEquals(result, referenceResult);
- if (j % 100 == 0) {
- checkEquality(testMap, referenceMap);
- }
- }
- }
-
- if (random.nextInt(20) == 0) {
- removeElement(random.nextInt(100), testMap, referenceMap);
- }
- }
- }
- }
-
- private static void removeElement(int index, EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
- Assert.assertEquals(referenceMap.size(), map.size());
- MapCursor<?, ?> cursor = map.getEntries();
- MapCursor<?, ?> referenceCursor = referenceMap.getEntries();
- int z = 0;
- while (cursor.advance()) {
- Assert.assertTrue(referenceCursor.advance());
- Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
- Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
- if (index == z) {
- cursor.remove();
- referenceCursor.remove();
- }
- ++z;
- }
-
- Assert.assertFalse(referenceCursor.advance());
- }
-
- private static void checkEquality(EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
- Assert.assertEquals(referenceMap.size(), map.size());
-
- // Check entries.
- UnmodifiableMapCursor<?, ?> cursor = map.getEntries();
- UnmodifiableMapCursor<?, ?> referenceCursor = referenceMap.getEntries();
- while (cursor.advance()) {
- Assert.assertTrue(referenceCursor.advance());
- Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
- Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
- }
-
- // Check keys.
- Iterator<?> iterator = map.getKeys().iterator();
- Iterator<?> referenceIterator = referenceMap.getKeys().iterator();
- while (iterator.hasNext()) {
- Assert.assertTrue(referenceIterator.hasNext());
- Assert.assertEquals(iterator.next(), referenceIterator.next());
- }
-
- // Check values.
- iterator = map.getValues().iterator();
- referenceIterator = referenceMap.getValues().iterator();
- while (iterator.hasNext()) {
- Assert.assertTrue(referenceIterator.hasNext());
- Assert.assertEquals(iterator.next(), referenceIterator.next());
- }
- Assert.assertFalse(referenceIterator.hasNext());
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.LinkedHashMap;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EconomicMapTest {
-
- @Test
- public void testMapGetDefault() {
- EconomicMap<Integer, Integer> map = EconomicMap.create();
- map.put(0, 1);
- Assert.assertEquals(map.get(0, 2), Integer.valueOf(1));
- Assert.assertEquals(map.get(1, 2), Integer.valueOf(2));
- }
-
- @Test
- public void testMapPutAll() {
- EconomicMap<Integer, Integer> map = EconomicMap.create();
- EconomicMap<Integer, Integer> newMap = EconomicMap.wrapMap(new LinkedHashMap<>());
- newMap.put(1, 1);
- newMap.put(2, 4);
- map.putAll(newMap);
- Assert.assertEquals(map.size(), 2);
-
- UnmodifiableEconomicMap<Integer, Integer> unmodifiableEconomicMap = EconomicMap.create(newMap);
-
- map.removeKey(1);
- map.put(2, 2);
- map.put(3, 9);
-
- map.putAll(unmodifiableEconomicMap);
- Assert.assertEquals(map.size(), 3);
- Assert.assertEquals(map.get(2), Integer.valueOf(4));
- }
-
- @Test
- public void testToString() {
- EconomicMap<Integer, Integer> map = EconomicMap.create();
- map.put(0, 0);
- map.put(1, 1);
- Assert.assertEquals(map.toString(), "map(size=2, {(0,0),(1,1)})");
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EconomicSetTest {
-
- @Test
- public void testUtilities() {
- EconomicSet<Integer> set = EconomicSet.create(0);
- set.add(0);
- Assert.assertTrue(set.add(1));
- Assert.assertEquals(set.size(), 2);
- Assert.assertFalse(set.add(1));
- Assert.assertEquals(set.size(), 2);
- set.remove(1);
- Assert.assertEquals(set.size(), 1);
- set.remove(2);
- Assert.assertEquals(set.size(), 1);
- Assert.assertTrue(set.add(1));
- set.clear();
- Assert.assertEquals(set.size(), 0);
- }
-
- @Test
- public void testAddAll() {
- EconomicSet<Integer> set = EconomicSet.create();
- set.addAll(Arrays.asList(0, 1, 0));
- Assert.assertEquals(set.size(), 2);
-
- EconomicSet<Integer> newSet = EconomicSet.create();
- newSet.addAll(Arrays.asList(1, 2));
- Assert.assertEquals(newSet.size(), 2);
- newSet.addAll(set);
- Assert.assertEquals(newSet.size(), 3);
- }
-
- @Test
- public void testRemoveAll() {
- EconomicSet<Integer> set = EconomicSet.create();
- set.addAll(Arrays.asList(0, 1));
-
- set.removeAll(Arrays.asList(1, 2));
- Assert.assertEquals(set.size(), 1);
-
- set.removeAll(EconomicSet.create(set));
- Assert.assertEquals(set.size(), 0);
- }
-
- @Test
- public void testRetainAll() {
- EconomicSet<Integer> set = EconomicSet.create();
- set.addAll(Arrays.asList(0, 1, 2));
-
- EconomicSet<Integer> newSet = EconomicSet.create();
- newSet.addAll(Arrays.asList(2, 3));
-
- set.retainAll(newSet);
- Assert.assertEquals(set.size(), 1);
- }
-
- @Test
- public void testToArray() {
- EconomicSet<Integer> set = EconomicSet.create();
- set.addAll(Arrays.asList(0, 1));
- Assert.assertArrayEquals(set.toArray(new Integer[2]), new Integer[]{0, 1});
- }
-
- @Test
- public void testToString() {
- EconomicSet<Integer> set = EconomicSet.create();
- set.addAll(Arrays.asList(0, 1));
- Assert.assertEquals(set.toString(), "set(size=2, {0,1})");
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testToUnalignedArray() {
- Assert.assertArrayEquals(EconomicSet.create().toArray(new Integer[2]), new Integer[0]);
- }
-
- @Test
- public void testSetRemoval() {
- ArrayList<Integer> initialList = new ArrayList<>();
- ArrayList<Integer> removalList = new ArrayList<>();
- ArrayList<Integer> finalList = new ArrayList<>();
- EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
- set.add(1);
- set.add(2);
- set.add(3);
- set.add(4);
- set.add(5);
- set.add(6);
- set.add(7);
- set.add(8);
- set.add(9);
- Iterator<Integer> i1 = set.iterator();
- while (i1.hasNext()) {
- initialList.add(i1.next());
- }
- int size = 0;
- Iterator<Integer> i2 = set.iterator();
- while (i2.hasNext()) {
- Integer elem = i2.next();
- if (size++ < 8) {
- i2.remove();
- }
- removalList.add(elem);
- }
- Iterator<Integer> i3 = set.iterator();
- while (i3.hasNext()) {
- finalList.add(i3.next());
- }
- Assert.assertEquals(initialList, removalList);
- Assert.assertEquals(1, finalList.size());
- Assert.assertEquals(new Integer(9), finalList.get(0));
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import org.graalvm.collections.Equivalence;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EquivalenceTest {
-
- private static final String TEST_STRING = "Graal";
- private static final String TEST_STRING2 = "Graal2";
-
- @Test
- public void testDEFAULT() {
- Assert.assertTrue(Equivalence.DEFAULT.equals(TEST_STRING, new String(TEST_STRING)));
- Assert.assertEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(new String(TEST_STRING)));
- Assert.assertFalse(Equivalence.DEFAULT.equals(TEST_STRING, TEST_STRING2));
- Assert.assertNotEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(TEST_STRING2));
- }
-
- @Test
- public void testIDENTITY() {
- Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, new String(TEST_STRING)));
- Assert.assertEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(new String(TEST_STRING)));
- Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, TEST_STRING2));
- Assert.assertNotEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(TEST_STRING2));
- }
-
- @Test
- public void testIDENTITYWITHSYSTEMHASHCODE() {
- Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, new String(TEST_STRING)));
- Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(new String(TEST_STRING)));
- Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, TEST_STRING2));
- Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING2));
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import org.graalvm.collections.Pair;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class PairTest {
-
- @Test
- public void testCreate() {
- Assert.assertEquals(Pair.create(null, null), Pair.empty());
- Assert.assertNotEquals(Pair.create(null, null), null);
- Assert.assertEquals(Pair.createLeft(null), Pair.empty());
- Assert.assertEquals(Pair.createRight(null), Pair.empty());
- Assert.assertEquals(Pair.create(1, null), Pair.createLeft(1));
- Assert.assertEquals(Pair.create(null, 1), Pair.createRight(1));
- }
-
- @Test
- public void testUtilities() {
- Pair<Integer, Integer> pair = Pair.create(1, null);
- Assert.assertEquals(pair.getLeft(), Integer.valueOf(1));
- Assert.assertEquals(pair.getRight(), null);
- Assert.assertEquals(pair.toString(), "(1, null)");
- Assert.assertEquals(pair.hashCode(), Pair.createLeft(1).hashCode());
- }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.function.BiFunction;
-
-/**
- * Memory efficient map data structure.
- *
- * @since 1.0
- */
-public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
-
- /**
- * Associates {@code value} with {@code key} in this map. If the map previously contained a
- * mapping for {@code key}, the old value is replaced by {@code value}.
- *
- * @return the previous value associated with {@code key}, or {@code null} if there was no
- * mapping for {@code key}.
- * @since 1.0
- */
- V put(K key, V value);
-
- /**
- * Copies all of the mappings from {@code other} to this map.
- *
- * @since 1.0
- */
- default void putAll(EconomicMap<K, V> other) {
- MapCursor<K, V> e = other.getEntries();
- while (e.advance()) {
- put(e.getKey(), e.getValue());
- }
- }
-
- /**
- * Copies all of the mappings from {@code other} to this map.
- *
- * @since 1.0
- */
- default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
- UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
- while (entry.advance()) {
- put(entry.getKey(), entry.getValue());
- }
- }
-
- /**
- * Removes all of the mappings from this map. The map will be empty after this call returns.
- *
- * @since 1.0
- */
- void clear();
-
- /**
- * Removes the mapping for {@code key} from this map if it is present. The map will not contain
- * a mapping for {@code key} once the call returns.
- *
- * @return the previous value associated with {@code key}, or {@code null} if there was no
- * mapping for {@code key}.
- * @since 1.0
- */
- V removeKey(K key);
-
- /**
- * Returns a {@link MapCursor} view of the mappings contained in this map.
- *
- * @since 1.0
- */
- @Override
- MapCursor<K, V> getEntries();
-
- /**
- * Replaces each entry's value with the result of invoking {@code function} on that entry until
- * all entries have been processed or the function throws an exception. Exceptions thrown by the
- * function are relayed to the caller.
- *
- * @since 1.0
- */
- void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
-
- /**
- * 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
- */
- static <K, V> EconomicMap<K, V> create() {
- return EconomicMap.create(Equivalence.DEFAULT);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set with the default
- * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
- * capacity.
- *
- * @since 1.0
- */
- static <K, V> EconomicMap<K, V> create(int initialCapacity) {
- return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set with the given comparison
- * strategy for keys.
- *
- * @since 1.0
- */
- static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
- return EconomicMapImpl.create(strategy, false);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set with the default
- * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
- * specified existing map.
- *
- * @since 1.0
- */
- static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
- return EconomicMap.create(Equivalence.DEFAULT, m);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set and copies all elements from
- * the specified existing map.
- *
- * @since 1.0
- */
- static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
- return EconomicMapImpl.create(strategy, m, false);
- }
-
- /**
- * Creates a new map that guarantees insertion order on the key set and initializes with a
- * specified capacity.
- *
- * @since 1.0
- */
- static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
- return EconomicMapImpl.create(strategy, initialCapacity, false);
- }
-
- /**
- * Wraps an existing {@link Map} as an {@link EconomicMap}.
- *
- * @since 1.0
- */
- static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
- return new EconomicMap<K, V>() {
-
- @Override
- public V get(K key) {
- V result = map.get(key);
- return result;
- }
-
- @Override
- public V put(K key, V value) {
- V result = map.put(key, value);
- return result;
- }
-
- @Override
- public int size() {
- int result = map.size();
- return result;
- }
-
- @Override
- public boolean containsKey(K key) {
- return map.containsKey(key);
- }
-
- @Override
- public void clear() {
- map.clear();
- }
-
- @Override
- public V removeKey(K key) {
- V result = map.remove(key);
- return result;
- }
-
- @Override
- public Iterable<V> getValues() {
- return map.values();
- }
-
- @Override
- public Iterable<K> getKeys() {
- return map.keySet();
- }
-
- @Override
- public boolean isEmpty() {
- return map.isEmpty();
- }
-
- @Override
- public MapCursor<K, V> getEntries() {
- Iterator<java.util.Map.Entry<K, V>> iterator = map.entrySet().iterator();
- return new MapCursor<K, V>() {
-
- private Map.Entry<K, V> current;
-
- @Override
- public boolean advance() {
- boolean result = iterator.hasNext();
- if (result) {
- current = iterator.next();
- }
-
- return result;
- }
-
- @Override
- public K getKey() {
- return current.getKey();
- }
-
- @Override
- public V getValue() {
- return current.getValue();
- }
-
- @Override
- public void remove() {
- iterator.remove();
- }
- };
- }
-
- @Override
- public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
- map.replaceAll(function);
- }
- };
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,857 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Iterator;
-import java.util.Objects;
-import java.util.function.BiFunction;
-
-/**
- * Implementation of a map with a memory-efficient structure that always preserves insertion order
- * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal
- * {@link #INITIAL_CAPACITY} or smaller 256.
- *
- * The key/value pairs are kept in an expanding flat object array with keys at even indices and
- * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there
- * is no additional hash data structure and comparisons are done via linear checking of the
- * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an
- * object identity comparison), this limit below which the map is without an actual hash table is
- * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}.
- *
- * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash
- * array where an entry of 0 means no hit and otherwise denotes the entry number in the
- * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit
- * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of
- * integer values in other cases.
- *
- * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take
- * the place of the values in the {@link #entries} array.
- *
- * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the
- * map falls below a specific threshold, the map will be compressed via the
- * {@link #maybeCompress(int)} method.
- */
-final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
-
- /**
- * Initial number of key/value pair entries that is allocated in the first entries array.
- */
- private static final int INITIAL_CAPACITY = 4;
-
- /**
- * Maximum number of entries that are moved linearly forward if a key is removed.
- */
- private static final int COMPRESS_IMMEDIATE_CAPACITY = 8;
-
- /**
- * Minimum number of key/value pair entries added when the entries array is increased in size.
- */
- private static final int MIN_CAPACITY_INCREASE = 8;
-
- /**
- * Number of entries above which a hash table is created.
- */
- private static final int HASH_THRESHOLD = 4;
-
- /**
- * Number of entries above which a hash table is created when equality can be checked with
- * object identity.
- */
- private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8;
-
- /**
- * Maximum number of entries allowed in the map.
- */
- private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1;
-
- /**
- * Number of entries above which more than 1 byte is necessary for the hash index.
- */
- private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1);
-
- /**
- * Number of entries above which more than 2 bytes are are necessary for the hash index.
- */
- private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE);
-
- /**
- * Total number of entries (actual entries plus deleted entries).
- */
- private int totalEntries;
-
- /**
- * Number of deleted entries.
- */
- private int deletedEntries;
-
- /**
- * Entries array with even indices storing keys and odd indices storing values.
- */
- private Object[] entries;
-
- /**
- * Hash array that is interpreted either as byte or short or int array depending on number of
- * map entries.
- */
- private byte[] hashArray;
-
- /**
- * The strategy used for comparing keys or {@code null} for denoting special strategy
- * {@link Equivalence#IDENTITY}.
- */
- private final Equivalence strategy;
-
- /**
- * Intercept method for debugging purposes.
- */
- private static <K, V> EconomicMapImpl<K, V> intercept(EconomicMapImpl<K, V> map) {
- return map;
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, boolean isSet) {
- return intercept(new EconomicMapImpl<>(strategy, isSet));
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, int initialCapacity, boolean isSet) {
- return intercept(new EconomicMapImpl<>(strategy, initialCapacity, isSet));
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
- return intercept(new EconomicMapImpl<>(strategy, other, isSet));
- }
-
- public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
- return intercept(new EconomicMapImpl<>(strategy, other, isSet));
- }
-
- private EconomicMapImpl(Equivalence strategy, boolean isSet) {
- if (strategy == Equivalence.IDENTITY) {
- this.strategy = null;
- } else {
- this.strategy = strategy;
- }
- this.isSet = isSet;
- }
-
- private EconomicMapImpl(Equivalence strategy, int initialCapacity, boolean isSet) {
- this(strategy, isSet);
- init(initialCapacity);
- }
-
- private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
- this(strategy, isSet);
- if (!initFrom(other)) {
- init(other.size());
- putAll(other);
- }
- }
-
- private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
- this(strategy, isSet);
- if (!initFrom(other)) {
- init(other.size());
- addAll(other);
- }
- }
-
- @SuppressWarnings("unchecked")
- private boolean initFrom(Object o) {
- if (o instanceof EconomicMapImpl) {
- EconomicMapImpl<K, V> otherMap = (EconomicMapImpl<K, V>) o;
- // We are only allowed to directly copy if the strategies of the two maps are the same.
- if (strategy == otherMap.strategy) {
- totalEntries = otherMap.totalEntries;
- deletedEntries = otherMap.deletedEntries;
- if (otherMap.entries != null) {
- entries = otherMap.entries.clone();
- }
- if (otherMap.hashArray != null) {
- hashArray = otherMap.hashArray.clone();
- }
- return true;
- }
- }
- return false;
- }
-
- private void init(int size) {
- if (size > INITIAL_CAPACITY) {
- entries = new Object[size << 1];
- }
- }
-
- /**
- * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from
- * other map on construction.
- */
- private static final class CollisionLink {
-
- CollisionLink(Object value, int next) {
- this.value = value;
- this.next = next;
- }
-
- final Object value;
-
- /**
- * Index plus one of the next entry in the collision link chain.
- */
- final int next;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V get(K key) {
- Objects.requireNonNull(key);
-
- int index = find(key);
- if (index != -1) {
- return (V) getValue(index);
- }
- return null;
- }
-
- private int find(K key) {
- if (hasHashArray()) {
- return findHash(key);
- } else {
- return findLinear(key);
- }
- }
-
- private int findLinear(K key) {
- for (int i = 0; i < totalEntries; i++) {
- Object entryKey = entries[i << 1];
- if (entryKey != null && compareKeys(key, entryKey)) {
- return i;
- }
- }
- return -1;
- }
-
- private boolean compareKeys(Object key, Object entryKey) {
- if (key == entryKey) {
- return true;
- }
- if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
- if (strategy == Equivalence.DEFAULT) {
- return key.equals(entryKey);
- } else {
- return strategy.equals(key, entryKey);
- }
- }
- return false;
- }
-
- private int findHash(K key) {
- int index = getHashArray(getHashIndex(key)) - 1;
- if (index != -1) {
- Object entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- return index;
- } else {
- Object entryValue = getRawValue(index);
- if (entryValue instanceof CollisionLink) {
- return findWithCollision(key, (CollisionLink) entryValue);
- }
- }
- }
-
- return -1;
- }
-
- private int findWithCollision(K key, CollisionLink initialEntryValue) {
- int index;
- Object entryKey;
- CollisionLink entryValue = initialEntryValue;
- while (true) {
- CollisionLink collisionLink = entryValue;
- index = collisionLink.next;
- entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- return index;
- } else {
- Object value = getRawValue(index);
- if (value instanceof CollisionLink) {
- entryValue = (CollisionLink) getRawValue(index);
- } else {
- return -1;
- }
- }
- }
- }
-
- private int getHashArray(int index) {
- if (entries.length < LARGE_HASH_THRESHOLD) {
- return (hashArray[index] & 0xFF);
- } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
- int adjustedIndex = index << 1;
- return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8);
- } else {
- int adjustedIndex = index << 2;
- return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24);
- }
- }
-
- private void setHashArray(int index, int value) {
- if (entries.length < LARGE_HASH_THRESHOLD) {
- hashArray[index] = (byte) value;
- } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
- int adjustedIndex = index << 1;
- hashArray[adjustedIndex] = (byte) value;
- hashArray[adjustedIndex + 1] = (byte) (value >> 8);
- } else {
- int adjustedIndex = index << 2;
- hashArray[adjustedIndex] = (byte) value;
- hashArray[adjustedIndex + 1] = (byte) (value >> 8);
- hashArray[adjustedIndex + 2] = (byte) (value >> 16);
- hashArray[adjustedIndex + 3] = (byte) (value >> 24);
- }
- }
-
- private int findAndRemoveHash(Object key) {
- int hashIndex = getHashIndex(key);
- int index = getHashArray(hashIndex) - 1;
- if (index != -1) {
- Object entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- Object value = getRawValue(index);
- int nextIndex = -1;
- if (value instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) value;
- nextIndex = collisionLink.next;
- }
- setHashArray(hashIndex, nextIndex + 1);
- return index;
- } else {
- Object entryValue = getRawValue(index);
- if (entryValue instanceof CollisionLink) {
- return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index);
- }
- }
- }
-
- return -1;
- }
-
- private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) {
- int index;
- Object entryKey;
- CollisionLink entryValue = initialEntryValue;
- int lastIndex = initialIndexValue;
- while (true) {
- CollisionLink collisionLink = entryValue;
- index = collisionLink.next;
- entryKey = getKey(index);
- if (compareKeys(key, entryKey)) {
- Object value = getRawValue(index);
- if (value instanceof CollisionLink) {
- CollisionLink thisCollisionLink = (CollisionLink) value;
- setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next));
- } else {
- setRawValue(lastIndex, collisionLink.value);
- }
- return index;
- } else {
- Object value = getRawValue(index);
- if (value instanceof CollisionLink) {
- entryValue = (CollisionLink) getRawValue(index);
- lastIndex = index;
- } else {
- return -1;
- }
- }
- }
- }
-
- private int getHashIndex(Object key) {
- int hash;
- if (strategy != null && strategy != Equivalence.DEFAULT) {
- if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
- hash = System.identityHashCode(key);
- } else {
- hash = strategy.hashCode(key);
- }
- } else {
- hash = key.hashCode();
- }
- hash = hash ^ (hash >>> 16);
- return hash & (getHashTableSize() - 1);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V put(K key, V value) {
- if (key == null) {
- throw new UnsupportedOperationException("null not supported as key!");
- }
- int index = find(key);
- if (index != -1) {
- Object oldValue = getValue(index);
- setValue(index, value);
- return (V) oldValue;
- }
-
- int nextEntryIndex = totalEntries;
- if (entries == null) {
- entries = new Object[INITIAL_CAPACITY << 1];
- } else if (entries.length == nextEntryIndex << 1) {
- grow();
-
- assert entries.length > totalEntries << 1;
- // Can change if grow is actually compressing.
- nextEntryIndex = totalEntries;
- }
-
- setKey(nextEntryIndex, key);
- setValue(nextEntryIndex, value);
- totalEntries++;
-
- if (hasHashArray()) {
- // Rehash on collision if hash table is more than three quarters full.
- boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1)));
- putHashEntry(key, nextEntryIndex, rehashOnCollision);
- } else if (totalEntries > getHashThreshold()) {
- createHash();
- }
-
- return null;
- }
-
- /**
- * Number of entries above which a hash table should be constructed.
- */
- private int getHashThreshold() {
- if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
- return HASH_THRESHOLD_IDENTITY_COMPARE;
- } else {
- return HASH_THRESHOLD;
- }
- }
-
- private void grow() {
- int entriesLength = entries.length;
- int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2);
- if (newSize > MAX_ELEMENT_COUNT) {
- throw new UnsupportedOperationException("map grown too large!");
- }
- Object[] newEntries = new Object[newSize << 1];
- System.arraycopy(entries, 0, newEntries, 0, entriesLength);
- entries = newEntries;
- if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) ||
- (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) {
- // Rehash in order to change number of bits reserved for hash indices.
- createHash();
- }
- }
-
- /**
- * Compresses the graph if there is a large number of deleted entries and returns the translated
- * new next index.
- */
- private int maybeCompress(int nextIndex) {
- if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) {
- return compressLarge(nextIndex);
- }
- return nextIndex;
- }
-
- /**
- * Compresses the graph and returns the translated new next index.
- */
- private int compressLarge(int nextIndex) {
- int size = INITIAL_CAPACITY;
- int remaining = totalEntries - deletedEntries;
-
- while (size <= remaining) {
- size += Math.max(MIN_CAPACITY_INCREASE, size >> 1);
- }
-
- Object[] newEntries = new Object[size << 1];
- int z = 0;
- int newNextIndex = remaining;
- for (int i = 0; i < totalEntries; ++i) {
- Object key = getKey(i);
- if (i == nextIndex) {
- newNextIndex = z;
- }
- if (key != null) {
- newEntries[z << 1] = key;
- newEntries[(z << 1) + 1] = getValue(i);
- z++;
- }
- }
-
- this.entries = newEntries;
- totalEntries = z;
- deletedEntries = 0;
- if (z <= getHashThreshold()) {
- this.hashArray = null;
- } else {
- createHash();
- }
- return newNextIndex;
- }
-
- private int getHashTableSize() {
- if (entries.length < LARGE_HASH_THRESHOLD) {
- return hashArray.length;
- } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
- return hashArray.length >> 1;
- } else {
- return hashArray.length >> 2;
- }
- }
-
- private void createHash() {
- int entryCount = size();
-
- // Calculate smallest 2^n that is greater number of entries.
- int size = getHashThreshold();
- while (size <= entryCount) {
- size <<= 1;
- }
-
- // Give extra size to avoid collisions.
- size <<= 1;
-
- if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) {
- // Every entry has 4 bytes.
- size <<= 2;
- } else if (this.entries.length >= LARGE_HASH_THRESHOLD) {
- // Every entry has 2 bytes.
- size <<= 1;
- } else {
- // Entries are very small => give extra size to further reduce collisions.
- size <<= 1;
- }
-
- hashArray = new byte[size];
- for (int i = 0; i < totalEntries; i++) {
- Object entryKey = getKey(i);
- if (entryKey != null) {
- putHashEntry(entryKey, i, false);
- }
- }
- }
-
- private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) {
- int hashIndex = getHashIndex(key);
- int oldIndex = getHashArray(hashIndex) - 1;
- if (oldIndex != -1 && rehashOnCollision) {
- this.createHash();
- return;
- }
- setHashArray(hashIndex, entryIndex + 1);
- Object value = getRawValue(entryIndex);
- if (oldIndex != -1) {
- assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle";
- if (value instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) value;
- setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex));
- } else {
- setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex));
- }
- } else {
- if (value instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) value;
- setRawValue(entryIndex, collisionLink.value);
- }
- }
- }
-
- @Override
- public int size() {
- return totalEntries - deletedEntries;
- }
-
- @Override
- public boolean containsKey(K key) {
- return find(key) != -1;
- }
-
- @Override
- public void clear() {
- entries = null;
- hashArray = null;
- totalEntries = deletedEntries = 0;
- }
-
- private boolean hasHashArray() {
- return hashArray != null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V removeKey(K key) {
- if (key == null) {
- throw new UnsupportedOperationException("null not supported as key!");
- }
- int index;
- if (hasHashArray()) {
- index = this.findAndRemoveHash(key);
- } else {
- index = this.findLinear(key);
- }
-
- if (index != -1) {
- Object value = getValue(index);
- remove(index);
- return (V) value;
- }
- return null;
- }
-
- /**
- * Removes the element at the specific index and returns the index of the next element. This can
- * be a different value if graph compression was triggered.
- */
- private int remove(int indexToRemove) {
- int index = indexToRemove;
- int entriesAfterIndex = totalEntries - index - 1;
- int result = index + 1;
-
- // Without hash array, compress immediately.
- if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) {
- while (index < totalEntries - 1) {
- setKey(index, getKey(index + 1));
- setRawValue(index, getRawValue(index + 1));
- index++;
- }
- result--;
- }
-
- setKey(index, null);
- setRawValue(index, null);
- if (index == totalEntries - 1) {
- // Make sure last element is always non-null.
- totalEntries--;
- while (index > 0 && getKey(index - 1) == null) {
- totalEntries--;
- deletedEntries--;
- index--;
- }
- } else {
- deletedEntries++;
- result = maybeCompress(result);
- }
-
- return result;
- }
-
- private abstract class SparseMapIterator<E> implements Iterator<E> {
-
- protected int current;
-
- @Override
- public boolean hasNext() {
- return current < totalEntries;
- }
-
- @Override
- public void remove() {
- if (hasHashArray()) {
- EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1));
- }
- current = EconomicMapImpl.this.remove(current - 1);
- }
- }
-
- @Override
- public Iterable<V> getValues() {
- return new Iterable<V>() {
- @Override
- public Iterator<V> iterator() {
- return new SparseMapIterator<V>() {
- @SuppressWarnings("unchecked")
- @Override
- public V next() {
- Object result;
- while (true) {
- result = getValue(current);
- if (result == null && getKey(current) == null) {
- // values can be null, double-check if key is also null
- current++;
- } else {
- current++;
- break;
- }
- }
- return (V) result;
- }
- };
- }
- };
- }
-
- @Override
- public Iterable<K> getKeys() {
- return this;
- }
-
- @Override
- public boolean isEmpty() {
- return this.size() == 0;
- }
-
- @Override
- public MapCursor<K, V> getEntries() {
- return new MapCursor<K, V>() {
- int current = -1;
-
- @Override
- public boolean advance() {
- current++;
- if (current >= totalEntries) {
- return false;
- } else {
- while (EconomicMapImpl.this.getKey(current) == null) {
- // Skip over null entries
- current++;
- }
- return true;
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public K getKey() {
- return (K) EconomicMapImpl.this.getKey(current);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public V getValue() {
- return (V) EconomicMapImpl.this.getValue(current);
- }
-
- @Override
- public void remove() {
- if (hasHashArray()) {
- EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current));
- }
- current = EconomicMapImpl.this.remove(current) - 1;
- }
- };
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
- for (int i = 0; i < totalEntries; i++) {
- Object entryKey = getKey(i);
- if (entryKey != null) {
- Object newValue = function.apply((K) entryKey, (V) getValue(i));
- setValue(i, newValue);
- }
- }
- }
-
- private Object getKey(int index) {
- return entries[index << 1];
- }
-
- private void setKey(int index, Object newValue) {
- entries[index << 1] = newValue;
- }
-
- private void setValue(int index, Object newValue) {
- Object oldValue = getRawValue(index);
- if (oldValue instanceof CollisionLink) {
- CollisionLink collisionLink = (CollisionLink) oldValue;
- setRawValue(index, new CollisionLink(newValue, collisionLink.next));
- } else {
- setRawValue(index, newValue);
- }
- }
-
- private void setRawValue(int index, Object newValue) {
- entries[(index << 1) + 1] = newValue;
- }
-
- private Object getRawValue(int index) {
- return entries[(index << 1) + 1];
- }
-
- private Object getValue(int index) {
- Object object = getRawValue(index);
- if (object instanceof CollisionLink) {
- return ((CollisionLink) object).value;
- }
- return object;
- }
-
- private final boolean isSet;
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append(isSet ? "set(size=" : "map(size=").append(size()).append(", {");
- String sep = "";
- MapCursor<K, V> cursor = getEntries();
- while (cursor.advance()) {
- builder.append(sep);
- if (isSet) {
- builder.append(cursor.getKey());
- } else {
- builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append(")");
- }
- sep = ",";
- }
- builder.append("})");
- return builder.toString();
- }
-
- @Override
- public Iterator<K> iterator() {
- return new SparseMapIterator<K>() {
- @SuppressWarnings("unchecked")
- @Override
- public K next() {
- Object result;
- while ((result = getKey(current++)) == null) {
- // skip null entries
- }
- return (K) result;
- }
- };
- }
-
- @Override
- public boolean contains(K element) {
- return containsKey(element);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean add(K element) {
- return put(element, (V) element) == null;
- }
-
- @Override
- public void remove(K element) {
- removeKey(element);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Iterator;
-
-/**
- * Memory efficient set data structure.
- *
- * @since 1.0
- */
-public interface EconomicSet<E> extends UnmodifiableEconomicSet<E> {
-
- /**
- * 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
- */
- boolean add(E element);
-
- /**
- * Removes {@code element} from this set if it is present. This set will not contain
- * {@code element} once the call returns.
- *
- * @since 1.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
- */
- void clear();
-
- /**
- * Adds all of the elements in {@code other} to this set if they're not already present.
- *
- * @since 1.0
- */
- default void addAll(EconomicSet<E> other) {
- addAll(other.iterator());
- }
-
- /**
- * Adds all of the elements in {@code values} to this set if they're not already present.
- *
- * @since 1.0
- */
- default void addAll(Iterable<E> values) {
- addAll(values.iterator());
- }
-
- /**
- * Adds all of the elements enumerated by {@code iterator} to this set if they're not already
- * present.
- *
- * @since 1.0
- */
- default void addAll(Iterator<E> iterator) {
- while (iterator.hasNext()) {
- add(iterator.next());
- }
- }
-
- /**
- * Removes from this set all of its elements that are contained in {@code other}.
- *
- * @since 1.0
- */
- default void removeAll(EconomicSet<E> other) {
- removeAll(other.iterator());
- }
-
- /**
- * Removes from this set all of its elements that are contained in {@code values}.
- *
- * @since 1.0
- */
- default void removeAll(Iterable<E> values) {
- removeAll(values.iterator());
- }
-
- /**
- * Removes from this set all of its elements that are enumerated by {@code iterator}.
- *
- * @since 1.0
- */
- default void removeAll(Iterator<E> iterator) {
- while (iterator.hasNext()) {
- remove(iterator.next());
- }
- }
-
- /**
- * Removes from this set all of its elements that are not contained in {@code other}.
- *
- * @since 1.0
- */
- default void retainAll(EconomicSet<E> other) {
- Iterator<E> iterator = iterator();
- while (iterator.hasNext()) {
- E key = iterator.next();
- if (!other.contains(key)) {
- iterator.remove();
- }
- }
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements with the
- * default {@link Equivalence#DEFAULT} comparison strategy.
- *
- * @since 1.0
- */
- static <E> EconomicSet<E> create() {
- return EconomicSet.create(Equivalence.DEFAULT);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements.
- *
- * @since 1.0
- */
- static <E> EconomicSet<E> create(Equivalence strategy) {
- return EconomicMapImpl.create(strategy, true);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements with the
- * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
- * specified collection.
- *
- * @since 1.0
- */
- static <E> EconomicSet<E> create(int initialCapacity) {
- return EconomicSet.create(Equivalence.DEFAULT, initialCapacity);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements with the
- * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
- * specified collection.
- *
- * @since 1.0
- */
- static <E> EconomicSet<E> create(UnmodifiableEconomicSet<E> c) {
- return EconomicSet.create(Equivalence.DEFAULT, c);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements and
- * initializes with the given capacity.
- *
- * @since 1.0
- */
- static <E> EconomicSet<E> create(Equivalence strategy, int initialCapacity) {
- return EconomicMapImpl.create(strategy, initialCapacity, true);
- }
-
- /**
- * Creates a new set guaranteeing insertion order when iterating over its elements and inserts
- * all elements of the specified collection.
- *
- * @since 1.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/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT},
- * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}.
- *
- * @since 1.0
- */
-public abstract class Equivalence {
-
- /**
- * Default equivalence calling {@link #equals(Object)} 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
- */
- public static final Equivalence DEFAULT = new Equivalence() {
-
- @Override
- public boolean equals(Object a, Object b) {
- return a.equals(b);
- }
-
- @Override
- public int hashCode(Object o) {
- return o.hashCode();
- }
- };
-
- /**
- * 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
- */
- public static final Equivalence IDENTITY = new Equivalence() {
-
- @Override
- public boolean equals(Object a, Object b) {
- return a == b;
- }
-
- @Override
- public int hashCode(Object o) {
- return o.hashCode();
- }
- };
-
- /**
- * Identity equivalence using {@code ==} to check equality and
- * {@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
- */
- public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() {
-
- @Override
- public boolean equals(Object a, Object b) {
- return a == b;
- }
-
- @Override
- public int hashCode(Object o) {
- return System.identityHashCode(o);
- }
- };
-
- /**
- * Subclass for creating custom equivalence definitions.
- *
- * @since 1.0
- */
- protected Equivalence() {
- }
-
- /**
- * Returns {@code true} if the non-{@code null} arguments are equal to each other and
- * {@code false} otherwise.
- *
- * @since 1.0
- */
- public abstract boolean equals(Object a, Object b);
-
- /**
- * Returns the hash code of a non-{@code null} argument {@code o}.
- *
- * @since 1.0
- */
- public abstract int hashCode(Object o);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Cursor to iterate over a mutable map.
- *
- * @since 1.0
- */
-public interface MapCursor<K, V> extends UnmodifiableMapCursor<K, V> {
- /**
- * Remove the current entry from the map. May only be called once. After calling
- * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on
- * the current entry.
- *
- * @since 1.0
- */
- void remove();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Objects;
-
-/**
- * Utility class representing a pair of values.
- *
- * @since 1.0
- */
-public final class Pair<L, R> {
-
- private static final Pair<Object, Object> EMPTY = new Pair<>(null, null);
-
- private final L left;
- private final R right;
-
- /**
- * Returns an empty pair.
- *
- * @since 1.0
- */
- @SuppressWarnings("unchecked")
- public static <L, R> Pair<L, R> empty() {
- return (Pair<L, R>) EMPTY;
- }
-
- /**
- * Constructs a pair with its left value being {@code left}, or returns an empty pair if
- * {@code left} is null.
- *
- * @return the constructed pair or an empty pair if {@code left} is null.
- * @since 1.0
- */
- public static <L, R> Pair<L, R> createLeft(L left) {
- if (left == null) {
- return empty();
- } else {
- return new Pair<>(left, null);
- }
- }
-
- /**
- * Constructs a pair with its right value being {@code right}, or returns an empty pair if
- * {@code right} is null.
- *
- * @return the constructed pair or an empty pair if {@code right} is null.
- * @since 1.0
- */
- public static <L, R> Pair<L, R> createRight(R right) {
- if (right == null) {
- return empty();
- } else {
- return new Pair<>(null, right);
- }
- }
-
- /**
- * Constructs a pair with its left value being {@code left}, and its right value being
- * {@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
- */
- public static <L, R> Pair<L, R> create(L left, R right) {
- if (right == null && left == null) {
- return empty();
- } else {
- return new Pair<>(left, right);
- }
- }
-
- private Pair(L left, R right) {
- this.left = left;
- this.right = right;
- }
-
- /**
- * Returns the left value of this pair.
- *
- * @since 1.0
- */
- public L getLeft() {
- return left;
- }
-
- /**
- * Returns the right value of this pair.
- *
- * @since 1.0
- */
- public R getRight() {
- return right;
- }
-
- /**
- * {@inheritDoc}
- *
- * @since 1.0
- */
- @Override
- public int hashCode() {
- return Objects.hashCode(left) + 31 * Objects.hashCode(right);
- }
-
- /**
- * {@inheritDoc}
- *
- * @since 1.0
- */
- @SuppressWarnings("unchecked")
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof Pair) {
- Pair<L, R> pair = (Pair<L, R>) obj;
- return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- *
- * @since 1.0
- */
- @Override
- public String toString() {
- return String.format("(%s, %s)", left, right);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Unmodifiable memory efficient map data structure.
- *
- * @since 1.0
- */
-public interface UnmodifiableEconomicMap<K, V> {
-
- /**
- * Returns the value to which {@code key} is mapped, or {@code null} if this map contains no
- * mapping for {@code key}.
- *
- * @since 1.0
- */
- V get(K key);
-
- /**
- * Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map
- * contains no mapping for {@code key}.
- *
- * @since 1.0
- */
- default V get(K key, V defaultValue) {
- V v = get(key);
- if (v == null) {
- return defaultValue;
- }
- return v;
- }
-
- /**
- * Returns {@code true} if this map contains a mapping for {@code key}.
- *
- * @since 1.0
- */
- boolean containsKey(K key);
-
- /**
- * Returns the number of key-value mappings in this map.
- *
- * @since 1.0
- */
- int size();
-
- /**
- * Returns {@code true} if this map contains no key-value mappings.
- *
- * @since 1.0
- */
- boolean isEmpty();
-
- /**
- * Returns a {@link Iterable} view of the values contained in this map.
- *
- * @since 1.0
- */
- Iterable<V> getValues();
-
- /**
- * Returns a {@link Iterable} view of the keys contained in this map.
- *
- * @since 1.0
- */
- Iterable<K> getKeys();
-
- /**
- * Returns a {@link UnmodifiableMapCursor} view of the mappings contained in this map.
- *
- * @since 1.0
- */
- UnmodifiableMapCursor<K, V> getEntries();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Unmodifiable memory efficient set data structure.
- *
- * @since 1.0
- */
-public interface UnmodifiableEconomicSet<E> extends Iterable<E> {
-
- /**
- * Returns {@code true} if this set contains a mapping for the {@code element}.
- *
- * @since 1.0
- */
- boolean contains(E element);
-
- /**
- * Returns the number of elements in this set.
- *
- * @since 1.0
- */
- int size();
-
- /**
- * Returns {@code true} if this set contains no elements.
- *
- * @since 1.0
- */
- boolean isEmpty();
-
- /**
- * Stores all of the elements in this set into {@code target}. An
- * {@link UnsupportedOperationException} will be thrown if the length of {@code target} does not
- * match the size of this set.
- *
- * @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
- */
- default E[] toArray(E[] target) {
- if (target.length != size()) {
- throw new UnsupportedOperationException("Length of target array must equal the size of the set.");
- }
-
- int index = 0;
- for (E element : this) {
- target[index++] = element;
- }
-
- return target;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Cursor to iterate over a map without changing its contents.
- *
- * @since 1.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
- */
- boolean advance();
-
- /**
- * The key of the current entry.
- *
- * @since 1.0
- */
- K getKey();
-
- /**
- * The value of the current entry.
- *
- * @since 1.0
- */
- V getValue();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/**
- * The Graal-SDK collections package contains memory efficient data structures.
- *
- * @see org.graalvm.collections.EconomicMap
- * @see org.graalvm.collections.EconomicSet
- *
- * @since 1.0
- */
-package org.graalvm.collections;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java Thu Apr 26 17:59:02 2018 +0200
@@ -206,12 +206,12 @@
}
@Override
- protected void bfm(int size, Register dst, Register src, int r, int s) {
+ public void bfm(int size, Register dst, Register src, int r, int s) {
super.bfm(size, dst, src, r, s);
}
@Override
- protected void ubfm(int size, Register dst, Register src, int r, int s) {
+ public void ubfm(int size, Register dst, Register src, int r, int s) {
super.ubfm(size, dst, src, r, s);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BLR;
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BR;
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BRK;
+import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CAS;
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX;
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS;
import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ;
@@ -118,6 +119,9 @@
import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
import org.graalvm.compiler.debug.GraalError;
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.aarch64.AArch64.CPUFeature;
+import jdk.vm.ci.aarch64.AArch64.Flag;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.TargetDescription;
@@ -471,6 +475,9 @@
private static final int BarrierOp = 0xD503301F;
private static final int BarrierKindOffset = 8;
+ private static final int CASAcquireOffset = 22;
+ private static final int CASReleaseOffset = 15;
+
/**
* Encoding for all instructions.
*/
@@ -501,6 +508,8 @@
LDP(0b1 << 22),
STP(0b0 << 22),
+ CAS(0x08A07C00),
+
ADR(0x00000000),
ADRP(0x80000000),
@@ -740,6 +749,14 @@
super(target);
}
+ public boolean supports(CPUFeature feature) {
+ return ((AArch64) target.arch).getFeatures().contains(feature);
+ }
+
+ public boolean isFlagSet(Flag flag) {
+ return ((AArch64) target.arch).getFlags().contains(flag);
+ }
+
/* Conditional Branch (5.2.1) */
/**
@@ -1311,6 +1328,20 @@
emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt));
}
+ /* Compare And Swap */
+ public void cas(int size, Register rs, Register rt, Register rn, boolean acquire, boolean release) {
+ assert size == 32 || size == 64;
+ int transferSize = NumUtil.log2Ceil(size / 8);
+ compareAndSwapInstruction(CAS, rs, rt, rn, transferSize, acquire, release);
+ }
+
+ private void compareAndSwapInstruction(Instruction instr, Register rs, Register rt, Register rn, int log2TransferSize, boolean acquire, boolean release) {
+ assert log2TransferSize >= 0 && log2TransferSize < 4;
+ assert rt.getRegisterCategory().equals(CPU) && rs.getRegisterCategory().equals(CPU) && !rs.equals(rt);
+ int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
+ emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt) | (acquire ? 1 : 0) << CASAcquireOffset | (release ? 1 : 0) << CASReleaseOffset);
+ }
+
/* PC-relative Address Calculation (5.4.4) */
/**
@@ -1576,7 +1607,7 @@
* @param r must be in the range 0 to size - 1
* @param s must be in the range 0 to size - 1
*/
- protected void bfm(int size, Register dst, Register src, int r, int s) {
+ public void bfm(int size, Register dst, Register src, int r, int s) {
bitfieldInstruction(BFM, dst, src, r, s, generalFromSize(size));
}
@@ -1589,7 +1620,7 @@
* @param r must be in the range 0 to size - 1
* @param s must be in the range 0 to size - 1
*/
- protected void ubfm(int size, Register dst, Register src, int r, int s) {
+ public void ubfm(int size, Register dst, Register src, int r, int s) {
bitfieldInstruction(UBFM, dst, src, r, s, generalFromSize(size));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
import java.util.List;
import java.util.Objects;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.graph.NodeSourcePosition;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
public abstract class SourceStackTraceBailoutException extends PermanentBailoutException {
private static final long serialVersionUID = 2144811793442316776L;
- public static SourceStackTraceBailoutException create(Throwable cause, String format, StackTraceElement[] elements) {
- return new SourceStackTraceBailoutException(cause, format) {
+ public static SourceStackTraceBailoutException create(Throwable cause, String reason, StackTraceElement[] elements) {
+ return new SourceStackTraceBailoutException(cause, reason) {
private static final long serialVersionUID = 6279381376051787907L;
@@ -46,7 +46,7 @@
};
}
- private SourceStackTraceBailoutException(Throwable cause, String format) {
- super(cause, format);
+ private SourceStackTraceBailoutException(Throwable cause, String reason) {
+ super(cause, "%s", reason);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,6 +42,7 @@
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
+import org.graalvm.compiler.lir.aarch64.AArch64ArrayCompareToOp;
import org.graalvm.compiler.lir.aarch64.AArch64ArrayEqualsOp;
import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp;
import org.graalvm.compiler.lir.aarch64.AArch64Compare;
@@ -51,13 +52,14 @@
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.TableSwitchOp;
import org.graalvm.compiler.lir.aarch64.AArch64Move;
-import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp;
+import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.CompareAndSwapOp;
import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
import org.graalvm.compiler.lir.aarch64.AArch64PauseOp;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGenerator;
import org.graalvm.compiler.phases.util.Providers;
+import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.aarch64.AArch64Kind;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.RegisterValue;
@@ -423,6 +425,21 @@
}
@Override
+ public Variable emitArrayCompareTo(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length1, Value length2) {
+ LIRKind resultKind = LIRKind.value(AArch64Kind.DWORD);
+ // DMS TODO: check calling conversion and registers used
+ RegisterValue res = AArch64.r0.asValue(resultKind);
+ RegisterValue cnt1 = AArch64.r1.asValue(length1.getValueKind());
+ RegisterValue cnt2 = AArch64.r2.asValue(length2.getValueKind());
+ emitMove(cnt1, length1);
+ emitMove(cnt2, length2);
+ append(new AArch64ArrayCompareToOp(this, kind1, kind2, res, array1, array2, cnt1, cnt2));
+ Variable result = newVariable(resultKind);
+ emitMove(result, res);
+ return result;
+ }
+
+ @Override
public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) {
Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD));
append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length)));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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.core.aarch64;
+
+import jdk.vm.ci.aarch64.AArch64Kind;
+
+import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.SignExtendNode;
+import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
+import org.graalvm.compiler.nodes.extended.GuardingNode;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+
+/**
+ * AArch64-specific subclass of ReadNode that knows how to merge ZeroExtend and SignExtend into the
+ * read.
+ */
+
+@NodeInfo
+public class AArch64ReadNode extends ReadNode {
+ public static final NodeClass<AArch64ReadNode> TYPE = NodeClass.create(AArch64ReadNode.class);
+ private final IntegerStamp accessStamp;
+ private final boolean isSigned;
+
+ public AArch64ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
+ FrameState stateBefore, IntegerStamp accessStamp, boolean isSigned) {
+ super(TYPE, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
+ this.accessStamp = accessStamp;
+ this.isSigned = isSigned;
+ }
+
+ @Override
+ public void generate(NodeLIRBuilderTool gen) {
+ AArch64LIRGenerator lirgen = (AArch64LIRGenerator) gen.getLIRGeneratorTool();
+ AArch64ArithmeticLIRGenerator arithgen = (AArch64ArithmeticLIRGenerator) lirgen.getArithmetic();
+ AArch64Kind readKind = (AArch64Kind) lirgen.getLIRKind(accessStamp).getPlatformKind();
+ int resultBits = ((IntegerStamp) stamp(NodeView.DEFAULT)).getBits();
+ gen.setResult(this, arithgen.emitExtendMemory(isSigned, readKind, resultBits, (AArch64AddressValue) gen.operand(getAddress()), gen.state(this)));
+ }
+
+ /**
+ * replace a ReadNode with an AArch64-specific variant which knows how to merge a downstream
+ * zero or sign extend into the read operation.
+ *
+ * @param readNode
+ */
+ public static void replace(ReadNode readNode) {
+ assert readNode.getUsageCount() == 1;
+ assert readNode.getUsageAt(0) instanceof ZeroExtendNode || readNode.getUsageAt(0) instanceof SignExtendNode;
+
+ ValueNode usage = (ValueNode) readNode.getUsageAt(0);
+ boolean isSigned = usage instanceof SignExtendNode;
+ IntegerStamp accessStamp = ((IntegerStamp) readNode.getAccessStamp());
+
+ AddressNode address = readNode.getAddress();
+ LocationIdentity location = readNode.getLocationIdentity();
+ Stamp stamp = usage.stamp(NodeView.DEFAULT);
+ GuardingNode guard = readNode.getGuard();
+ BarrierType barrierType = readNode.getBarrierType();
+ boolean nullCheck = readNode.getNullCheck();
+ FrameState stateBefore = readNode.stateBefore();
+ AArch64ReadNode clone = new AArch64ReadNode(address, location, stamp, guard, barrierType, nullCheck, stateBefore, accessStamp, isSigned);
+ StructuredGraph graph = readNode.graph();
+ graph.add(clone);
+ // splice out the extend node
+ usage.replaceAtUsagesAndDelete(readNode);
+ // swap the clone for the read
+ graph.replaceFixedWithFixed(readNode, clone);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadReplacementPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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.core.aarch64;
+
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.calc.SignExtendNode;
+import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.phases.Phase;
+
+/**
+ * AArch64-specific phase which substitutes certain read nodes with arch-specific variants in order
+ * to allow merging of zero and sign extension into the read operation.
+ */
+
+public class AArch64ReadReplacementPhase extends Phase {
+ @Override
+ protected void run(StructuredGraph graph) {
+ for (Node node : graph.getNodes()) {
+ // don't process nodes we just added
+ if (node instanceof AArch64ReadNode) {
+ continue;
+ }
+ if (node instanceof ReadNode) {
+ ReadNode readNode = (ReadNode) node;
+ if (readNode.hasExactlyOneUsage()) {
+ Node usage = readNode.getUsageAt(0);
+ if (usage instanceof ZeroExtendNode || usage instanceof SignExtendNode) {
+ AArch64ReadNode.replace(readNode);
+ }
+ }
+ }
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,14 +22,37 @@
*/
package org.graalvm.compiler.core.aarch64;
+import java.util.ListIterator;
+
import org.graalvm.compiler.java.DefaultSuitesCreator;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.Phase;
+import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.Suites;
public class AArch64SuitesCreator extends DefaultSuitesCreator {
+ private final Class<? extends Phase> insertReadReplacementBefore;
- public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) {
+ public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, Class<? extends Phase> insertReadReplacementBefore) {
super(compilerConfiguration, plugins);
+ this.insertReadReplacementBefore = insertReadReplacementBefore;
}
+ @Override
+ public Suites createSuites(OptionValues options) {
+ Suites suites = super.createSuites(options);
+
+ ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(insertReadReplacementBefore);
+ // Put AArch64ReadReplacementPhase right before the SchedulePhase
+ while (PhaseSuite.findNextPhase(findPhase, insertReadReplacementBefore)) {
+ // Search for last occurrence of SchedulePhase
+ }
+ findPhase.previous();
+ findPhase.add(new AArch64ReadReplacementPhase());
+ return suites;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.lir.VirtualStackSlot;
import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Thu Apr 26 17:59:02 2018 +0200
@@ -262,6 +262,9 @@
@Option(help = "Track the NodeSourcePosition.", type = OptionType.Debug)
public static final OptionKey<Boolean> TrackNodeSourcePosition = new OptionKey<>(false);
+ @Option(help = "Track source stack trace where a node was inserted into the graph.", type = OptionType.Debug)
+ public static final OptionKey<Boolean> TrackNodeInsertion = new OptionKey<>(false);
+
@Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug)
public static final OptionKey<Boolean> MatchExpressions = new OptionKey<>(true);
@@ -276,7 +279,10 @@
@Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug)
public static final OptionKey<Boolean> TraceRA = new OptionKey<>(false);
- @Option(help = "Enable tracing of inlining decision.", type = OptionType.Debug)
+
+ @Option(help = "file:doc-files/TraceInliningHelp.txt", type = OptionType.Debug)
public static final OptionKey<Boolean> TraceInlining = new OptionKey<>(false);
+ @Option(help = "Enable inlining decision tracing in stubs and snippets.", type = OptionType.Debug)
+ public static final OptionKey<Boolean> TraceInliningForStubsAndSnippets = new OptionKey<>(false);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
}
public PermanentBailoutException(String reason) {
- super(true, reason);
+ super(true, "%s", reason);
}
public PermanentBailoutException(Throwable cause, String format, Object... args) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
*/
package org.graalvm.compiler.core.common.alloc;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.GraalOptions;
import jdk.vm.ci.code.Register;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/doc-files/TraceInliningHelp.txt Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,8 @@
+Enable tracing of inlining decisions.
+Output format:
+ compilation of 'Signature of the compilation root method':
+ at 'Signature of the root method' ['Bytecode index']: <'Phase'> 'Child method signature': 'Decision made about this callsite'
+ at 'Signature of the child method' ['Bytecode index']:
+ |--<'Phase 1'> 'Grandchild method signature': 'First decision made about this callsite'
+ \--<'Phase 2'> 'Grandchild method signature': 'Second decision made about this callsite'
+ at 'Signature of the child method' ['Bytecode index']: <'Phase'> 'Another grandchild method signature': 'The only decision made about this callsite.'
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
package org.graalvm.compiler.core.common.spi;
import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.ValueKindFactory;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
/**
* Creates an array of T objects order by the occurrence frequency of each object. The most
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.core.common.util;
-
-import static org.graalvm.compiler.serviceprovider.JDK9Method.JAVA_SPECIFICATION_VERSION;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-import org.graalvm.compiler.debug.GraalError;
-
-/**
- * Reflection based access to the Module API introduced by JDK 9. This allows the API to be used in
- * code that must be compiled on a JDK prior to 9. Use of this class must be guarded by a test for
- * JDK 9 or later. For example:
- *
- * <pre>
- * if (Util.JAVA_SPECIFICATION_VERSION >= 9) {
- * // Use of ModuleAPI
- * }
- * </pre>
- */
-public final class ModuleAPI {
-
- public ModuleAPI(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
- try {
- this.method = declaringClass.getMethod(name, parameterTypes);
- } catch (Exception e) {
- throw new GraalError(e);
- }
- }
-
- public final Method method;
-
- public Class<?> getReturnType() {
- return method.getReturnType();
- }
-
- /**
- * {@code Class.getModule()}.
- */
- public static final ModuleAPI getModule;
-
- /**
- * {@code java.lang.Module.getResourceAsStream(String)}.
- */
- public static final ModuleAPI getResourceAsStream;
-
- /**
- * {@code java.lang.Module.isExported(String, Module)}.
- */
- public static final ModuleAPI isExportedTo;
-
- /**
- * Invokes the static Module API method represented by this object.
- */
- @SuppressWarnings("unchecked")
- public <T> T invokeStatic(Object... args) {
- checkAvailability();
- assert Modifier.isStatic(method.getModifiers());
- try {
- return (T) method.invoke(null, args);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- throw new GraalError(e);
- }
- }
-
- /**
- * Invokes the non-static Module API method represented by this object.
- */
- @SuppressWarnings("unchecked")
- public <T> T invoke(Object receiver, Object... args) {
- checkAvailability();
- assert !Modifier.isStatic(method.getModifiers());
- try {
- return (T) method.invoke(receiver, args);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- throw new GraalError(e);
- }
- }
-
- private void checkAvailability() throws GraalError {
- if (method == null) {
- throw new GraalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION);
- }
- }
-
- static {
- if (JAVA_SPECIFICATION_VERSION >= 9) {
- getModule = new ModuleAPI(Class.class, "getModule");
- Class<?> moduleClass = getModule.getReturnType();
- getResourceAsStream = new ModuleAPI(moduleClass, "getResourceAsStream", String.class);
- isExportedTo = new ModuleAPI(moduleClass, "isExported", String.class, moduleClass);
- } else {
- ModuleAPI unavailable = new ModuleAPI();
- getModule = unavailable;
- getResourceAsStream = unavailable;
- isExportedTo = unavailable;
- }
- }
-
- private ModuleAPI() {
- method = null;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java Thu Apr 26 17:59:02 2018 +0200
@@ -58,9 +58,9 @@
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.gen.NodeMatchRules;
import org.graalvm.compiler.core.match.ComplexMatchResult;
import org.graalvm.compiler.core.match.MatchRule;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Thu Apr 26 17:59:02 2018 +0200
@@ -80,7 +80,7 @@
import org.graalvm.compiler.phases.verify.VerifyUsageWithEquals;
import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage;
import org.graalvm.compiler.runtime.RuntimeProvider;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
@@ -103,14 +103,6 @@
*/
public class CheckGraalInvariants extends GraalCompilerTest {
- public CheckGraalInvariants() {
- try {
- Class.forName("java.lang.management.ManagementFactory");
- } catch (ClassNotFoundException ex) {
- Assume.assumeNoException("cannot run without java.management JDK9 module", ex);
- }
- }
-
private static boolean shouldVerifyEquals(ResolvedJavaMethod m) {
if (m.getName().equals("identityEquals")) {
ResolvedJavaType c = m.getDeclaringClass();
@@ -148,7 +140,7 @@
}
protected boolean shouldLoadClass(String className) {
- return !className.equals("module-info");
+ return !className.equals("module-info") && !className.startsWith("META-INF.versions.");
}
protected void handleClassLoadingException(Throwable t) {
@@ -191,7 +183,7 @@
for (final Enumeration<? extends ZipEntry> entry = zipFile.entries(); entry.hasMoreElements();) {
final ZipEntry zipEntry = entry.nextElement();
String name = zipEntry.getName();
- if (name.endsWith(".class")) {
+ if (name.endsWith(".class") && !name.startsWith("META-INF/versions/")) {
String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
if (isInNativeImage(className)) {
/*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.core.test;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugContext.Scope;
import org.graalvm.compiler.debug.DebugOptions;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,6 @@
import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions;
import static org.junit.Assert.assertNotNull;
-import org.junit.Test;
-
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
import org.graalvm.compiler.nodes.FullInfopointNode;
@@ -37,6 +35,7 @@
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Test;
import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.code.site.Infopoint;
@@ -50,6 +49,11 @@
public static final String[] STRINGS = new String[]{"world", "everyone", "you"};
+ public InfopointReasonTest() {
+ // Call testMethod to ensure all method references are resolved.
+ testMethod();
+ }
+
public String testMethod() {
StringBuilder sb = new StringBuilder("Hello ");
for (String s : STRINGS) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -116,6 +116,7 @@
@Test
public void testCompiled() throws IOException {
+ Assume.assumeFalse("Crashes on AArch64 (GR-8351)", System.getProperty("os.arch").equalsIgnoreCase("aarch64"));
ResolvedJavaMethod getMethod = asResolvedJavaMethod(getMethod(ByteBuffer.class, "get", new Class<?>[]{}));
ResolvedJavaType mbbClass = getMetaAccess().lookupJavaType(MappedByteBuffer.class);
ResolvedJavaMethod getMethodImpl = mbbClass.findUniqueConcreteMethod(getMethod).getResult();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
import org.graalvm.compiler.nodes.FieldLocationIdentity;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.memory.Access;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ResolvedJavaField;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java Thu Apr 26 17:59:02 2018 +0200
@@ -31,12 +31,13 @@
import java.util.Map;
import java.util.Properties;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionDescriptor;
import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
/**
@@ -108,8 +109,8 @@
ParameterizedType pt = (ParameterizedType) declaredType;
Type[] actualTypeArguments = pt.getActualTypeArguments();
assert actualTypeArguments.length == 1;
- Class<?> optionType = (Class<?>) actualTypeArguments[0];
- descriptors.put(fieldName, OptionDescriptor.create(fieldName, optionType, help, declaringClass, fieldName, (OptionKey<?>) f.get(null)));
+ Class<?> optionValueType = (Class<?>) actualTypeArguments[0];
+ descriptors.put(fieldName, OptionDescriptor.create(fieldName, OptionType.Debug, optionValueType, help, declaringClass, fieldName, (OptionKey<?>) f.get(null)));
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new IllegalArgumentException(e);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,6 @@
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
-import org.junit.Ignore;
import org.junit.Test;
import jdk.vm.ci.meta.JavaConstant;
@@ -36,21 +35,23 @@
*/
public class StampMemoryAccessTest extends GraalCompilerTest {
- @Ignore("not all JVMCI versions are safe yet")
@Test
public void testReadPrimitive() {
MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider();
- JavaConstant base = getSnippetReflection().forObject("");
Stamp stamp = StampFactory.forKind(JavaKind.Long);
- assertTrue(stamp.readConstant(memory, base, 128) == null);
+ JavaConstant objectBase = getSnippetReflection().forObject("");
+ assertTrue(stamp.readConstant(memory, objectBase, 128) == null);
+ JavaConstant arrayBase = getSnippetReflection().forObject(new int[]{});
+ assertTrue(stamp.readConstant(memory, arrayBase, 128) == null);
}
- @Ignore("not all JVMCI versions are safe yet")
@Test
public void testReadObject() {
MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider();
- JavaConstant base = getSnippetReflection().forObject("");
Stamp stamp = StampFactory.forKind(JavaKind.Object);
- assertTrue(stamp.readConstant(memory, base, 128) == null);
+ JavaConstant objectBase = getSnippetReflection().forObject("");
+ assertTrue(stamp.readConstant(memory, objectBase, 128) == null);
+ JavaConstant arrayBase = getSnippetReflection().forObject(new int[]{});
+ assertTrue(stamp.readConstant(memory, arrayBase, 128) == null);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -39,6 +39,7 @@
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Test;
import jdk.vm.ci.meta.JavaConstant;
@@ -405,6 +406,8 @@
*/
@Test
public void testNewNode() {
+ // Trackking of creation interferes with escape analysis
+ Assume.assumeFalse(Node.TRACK_CREATION_POSITION);
testEscapeAnalysis("testNewNodeSnippet", null, false);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,9 +22,11 @@
*/
package org.graalvm.compiler.core.test.inlining;
+import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugDumpScope;
+import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.FullInfopointNode;
import org.graalvm.compiler.nodes.Invoke;
@@ -32,18 +34,22 @@
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.StructuredGraph.Builder;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import jdk.vm.ci.code.site.InfopointReason;
import jdk.vm.ci.meta.ResolvedJavaMethod;
+import java.util.regex.Pattern;
+
public class InliningTest extends GraalCompilerTest {
@Test
@@ -198,6 +204,40 @@
assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", true)));
}
+ public static void traceInliningTest() {
+ callTrivial();
+ }
+
+ private static void callTrivial() {
+ callNonTrivial();
+ }
+
+ private static double callNonTrivial() {
+ double x = 0.0;
+ for (int i = 0; i < 10; i++) {
+ x += i * 1.21;
+ }
+ return x;
+ }
+
+ @Test
+ @SuppressWarnings("try")
+ public void testTracing() {
+ OptionValues options = new OptionValues(getInitialOptions(), GraalOptions.TraceInlining, true);
+ StructuredGraph graph;
+ try (TTY.Filter f = new TTY.Filter()) {
+ graph = getGraph("traceInliningTest", options, false);
+ }
+ String inliningTree = graph.getInliningLog().formatAsTree(false);
+ String expectedRegex = "compilation of org.graalvm.compiler.core.test.inlining.InliningTest.traceInliningTest.*: \\R" +
+ " at .*org.graalvm.compiler.core.test.inlining.InliningTest.traceInliningTest.*: <GraphBuilderPhase> org.graalvm.compiler.core.test.inlining.InliningTest.callTrivial.*: yes, inline method\\R" +
+ " at .*org.graalvm.compiler.core.test.inlining.InliningTest.callTrivial.*: .*\\R" +
+ " .*<GraphBuilderPhase> org.graalvm.compiler.core.test.inlining.InliningTest.callNonTrivial.*: .*(.*\\R)*" +
+ " .*<InliningPhase> org.graalvm.compiler.core.test.inlining.InliningTest.callNonTrivial.*: .*(.*\\R)*";
+ Pattern expectedPattern = Pattern.compile(expectedRegex, Pattern.MULTILINE);
+ Assert.assertTrue("Got: " + inliningTree, expectedPattern.matcher(inliningTree).matches());
+ }
+
@SuppressWarnings("all")
public static int invokeLeafClassMethodSnippet(SubClassA subClassA) {
return subClassA.publicFinalMethod() + subClassA.publicNotOverriddenMethod() + subClassA.publicOverriddenMethod();
@@ -233,9 +273,13 @@
return superClass.protectedOverriddenMethod();
}
+ private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
+ return getGraph(snippet, null, eagerInfopointMode);
+ }
+
@SuppressWarnings("try")
- private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
- DebugContext debug = getDebugContext();
+ private StructuredGraph getGraph(final String snippet, OptionValues options, final boolean eagerInfopointMode) {
+ DebugContext debug = options == null ? getDebugContext() : getDebugContext(options, null, null);
try (DebugContext.Scope s = debug.scope("InliningTest", new DebugDumpScope(snippet, true))) {
ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
Builder builder = builder(method, AllowAssumptions.YES, debug);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.TTY;
@@ -137,7 +137,8 @@
ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod();
for (int i = 0; i < inliningCount; i++) {
next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke();
- EconomicSet<Node> canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod);
+ EconomicSet<Node> canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod, null,
+ "Called explicitly from a unit test.", "Test case");
canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes);
callerGraph.getDebug().dump(DebugContext.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,10 +23,11 @@
package org.graalvm.compiler.core;
import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation;
+import static org.graalvm.compiler.serviceprovider.GraalServices.getCurrentThreadAllocatedBytes;
+import static org.graalvm.compiler.serviceprovider.GraalServices.isThreadAllocatedMemorySupported;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier;
-import org.graalvm.compiler.debug.Management;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.options.OptionValues;
@@ -58,11 +59,6 @@
*/
public static CompilationPrinter begin(OptionValues options, CompilationIdentifier id, JavaMethod method, int entryBCI) {
if (PrintCompilation.getValue(options) && !TTY.isSuppressed()) {
- try {
- Class.forName("java.lang.management.ManagementFactory");
- } catch (ClassNotFoundException ex) {
- throw new IllegalArgumentException("PrintCompilation option requires java.management module");
- }
return new CompilationPrinter(id, method, entryBCI);
}
return DISABLED;
@@ -83,9 +79,8 @@
this.id = id;
this.entryBCI = entryBCI;
- final long threadId = Thread.currentThread().getId();
start = System.nanoTime();
- allocatedBytesBefore = getAllocatedBytes(threadId);
+ allocatedBytesBefore = isThreadAllocatedMemorySupported() ? getCurrentThreadAllocatedBytes() : -1;
}
private String getMethodDescription() {
@@ -101,24 +96,17 @@
*/
public void finish(CompilationResult result) {
if (id != null) {
- final long threadId = Thread.currentThread().getId();
final long stop = System.nanoTime();
final long duration = (stop - start) / 1000000;
final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
final int bytecodeSize = result != null ? result.getBytecodeSize() : 0;
- final long allocatedBytesAfter = getAllocatedBytes(threadId);
- final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
-
- TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
+ if (allocatedBytesBefore == -1) {
+ TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB", duration, bytecodeSize, targetCodeSize));
+ } else {
+ final long allocatedBytesAfter = getCurrentThreadAllocatedBytes();
+ final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
+ TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
+ }
}
}
-
- static com.sun.management.ThreadMXBean threadMXBean;
-
- static long getAllocatedBytes(long threadId) {
- if (threadMXBean == null) {
- threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
- }
- return threadMXBean.getThreadAllocatedBytes(threadId);
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Thu Apr 26 17:59:02 2018 +0200
@@ -122,8 +122,10 @@
*
* Subclasses can override this to choose a different action based on factors such as whether
* {@code actionKey} has been explicitly set in {@code options} for example.
+ *
+ * @param cause the cause of the bailout or failure
*/
- protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey) {
+ protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
if (actionKey == CompilationFailureAction) {
if (ExitVMOnException.getValue(options)) {
assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
@@ -175,7 +177,7 @@
actionKey = CompilationFailureAction;
causeType = "failure";
}
- ExceptionAction action = lookupAction(initialOptions, actionKey);
+ ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
action = adjustAction(initialOptions, actionKey, action);
@@ -262,22 +264,34 @@
DumpPath, dumpPath.getPath());
try (DebugContext retryDebug = createRetryDebugContext(retryOptions)) {
- return performCompilation(retryDebug);
+ T res = performCompilation(retryDebug);
+ maybeExitVM(action);
+ return res;
} catch (Throwable ignore) {
// Failures during retry are silent
- return handleException(cause);
- } finally {
- if (action == ExitVM) {
- synchronized (ExceptionAction.class) {
- TTY.println("Exiting VM after retry compilation of " + this);
- System.exit(-1);
- }
- }
+ T res = handleException(cause);
+ maybeExitVM(action);
+ return res;
}
}
}
}
+ private void maybeExitVM(ExceptionAction action) {
+ if (action == ExitVM) {
+ synchronized (ExceptionAction.class) {
+ try {
+ // Give other compiler threads a chance to flush
+ // error handling output.
+ ExceptionAction.class.wait(2000);
+ } catch (InterruptedException e) {
+ }
+ TTY.println("Exiting VM after retry compilation of " + this);
+ System.exit(-1);
+ }
+ }
+ }
+
/**
* Adjusts {@code initialAction} if necessary based on
* {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,10 +25,12 @@
import java.util.Collection;
import java.util.List;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
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.alloc.ComputeBlockOrder;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
@@ -188,8 +190,18 @@
* {@code graph.method()} or {@code graph.name}
*/
private static void checkForRequestedCrash(StructuredGraph graph) {
- String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions());
- if (methodPattern != null) {
+ String value = GraalCompilerOptions.CrashAt.getValue(graph.getOptions());
+ if (value != null) {
+ boolean bailout = false;
+ boolean permanentBailout = false;
+ String methodPattern = value;
+ if (value.endsWith(":Bailout")) {
+ methodPattern = value.substring(0, value.length() - ":Bailout".length());
+ bailout = true;
+ } else if (value.endsWith(":PermanentBailout")) {
+ methodPattern = value.substring(0, value.length() - ":PermanentBailout".length());
+ permanentBailout = true;
+ }
String crashLabel = null;
if (graph.name != null && graph.name.contains(methodPattern)) {
crashLabel = graph.name;
@@ -204,6 +216,12 @@
}
}
if (crashLabel != null) {
+ if (permanentBailout) {
+ throw new PermanentBailoutException("Forced crash after compiling " + crashLabel);
+ }
+ if (bailout) {
+ throw new RetryableBailoutException("Forced crash after compiling " + crashLabel);
+ }
throw new RuntimeException("Forced crash after compiling " + crashLabel);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,12 +38,14 @@
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. " +
- "See the MethodFilter option for the pattern syntax. ", type = OptionType.Debug)
+ "See the MethodFilter option for the pattern syntax. A ':Bailout' " +
+ "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 = "file:doc-files/CompilationBailoutActionHelp.txt", type = OptionType.User)
public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent);
@Option(help = "Specifies the action to take when compilation fails with a bailout exception. " +
- "The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
+ "The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
@Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
"by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action.", type = OptionType.User)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.util.Arrays;
import java.util.Queue;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,8 +33,8 @@
import java.util.Collection;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
import java.util.Arrays;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.gen.NodeLIRBuilder;
import org.graalvm.compiler.core.match.MatchPattern.Result;
import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,9 +27,9 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.core.gen.NodeMatchRules;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
--- /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/phases/CommunityCompilerConfiguration.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.phases;
+
+import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
+import org.graalvm.compiler.lir.phases.AllocationStage;
+import org.graalvm.compiler.lir.phases.LIRPhaseSuite;
+import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
+import org.graalvm.compiler.lir.phases.PostAllocationOptimizationStage;
+import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
+import org.graalvm.compiler.lir.phases.PreAllocationOptimizationStage;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.MidTierContext;
+
+/**
+ * The default configuration for the community edition of Graal.
+ */
+public class CommunityCompilerConfiguration implements CompilerConfiguration {
+
+ @Override
+ public PhaseSuite<HighTierContext> createHighTier(OptionValues options) {
+ return new HighTier(options);
+ }
+
+ @Override
+ public PhaseSuite<MidTierContext> createMidTier(OptionValues options) {
+ return new MidTier(options);
+ }
+
+ @Override
+ public PhaseSuite<LowTierContext> createLowTier(OptionValues options) {
+ return new LowTier(options);
+ }
+
+ @Override
+ public LIRPhaseSuite<PreAllocationOptimizationContext> createPreAllocationOptimizationStage(OptionValues options) {
+ return new PreAllocationOptimizationStage(options);
+ }
+
+ @Override
+ public LIRPhaseSuite<AllocationContext> createAllocationStage(OptionValues options) {
+ return new AllocationStage(options);
+ }
+
+ @Override
+ public LIRPhaseSuite<PostAllocationOptimizationContext> createPostAllocationOptimizationStage(OptionValues options) {
+ return new PostAllocationOptimizationStage(options);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.core.phases;
-
-import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
-import org.graalvm.compiler.lir.phases.AllocationStage;
-import org.graalvm.compiler.lir.phases.LIRPhaseSuite;
-import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
-import org.graalvm.compiler.lir.phases.PostAllocationOptimizationStage;
-import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
-import org.graalvm.compiler.lir.phases.PreAllocationOptimizationStage;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.PhaseSuite;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.LowTierContext;
-import org.graalvm.compiler.phases.tiers.MidTierContext;
-
-public class CoreCompilerConfiguration implements CompilerConfiguration {
-
- @Override
- public PhaseSuite<HighTierContext> createHighTier(OptionValues options) {
- return new HighTier(options);
- }
-
- @Override
- public PhaseSuite<MidTierContext> createMidTier(OptionValues options) {
- return new MidTier(options);
- }
-
- @Override
- public PhaseSuite<LowTierContext> createLowTier(OptionValues options) {
- return new LowTier(options);
- }
-
- @Override
- public LIRPhaseSuite<PreAllocationOptimizationContext> createPreAllocationOptimizationStage(OptionValues options) {
- return new PreAllocationOptimizationStage(options);
- }
-
- @Override
- public LIRPhaseSuite<AllocationContext> createAllocationStage(OptionValues options) {
- return new AllocationStage(options);
- }
-
- @Override
- public LIRPhaseSuite<PostAllocationOptimizationContext> createPostAllocationOptimizationStage(OptionValues options) {
- return new PostAllocationOptimizationStage(options);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,6 +36,10 @@
import org.graalvm.compiler.phases.tiers.LowTierContext;
import org.graalvm.compiler.phases.tiers.MidTierContext;
+/**
+ * A compiler configuration that performs fewer Graal IR optimizations while using the same backend
+ * as the {@link CommunityCompilerConfiguration}.
+ */
public class EconomyCompilerConfiguration implements CompilerConfiguration {
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
*/
package org.graalvm.compiler.core.phases;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Graph.NodeEvent;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.ArrayList;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier;
@@ -41,6 +41,7 @@
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.GraphSpeculationLog;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.phases.tiers.TargetProvider;
@@ -209,7 +210,7 @@
try {
preCodeInstallationTasks(tasks, compilationResult, predefinedInstalledCode);
CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult);
- installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
+ installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, GraphSpeculationLog.unwrap(speculationLog), isDefault);
assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
} catch (Throwable t) {
failCodeInstallationTasks(tasks, t);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
import java.util.Formatter;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.Assertions;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,16 +28,14 @@
import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES;
import static org.junit.Assert.assertEquals;
-import java.lang.management.ThreadMXBean;
-
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.debug.Management;
import org.graalvm.compiler.debug.TimerKey;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -47,12 +45,7 @@
@Before
public void checkCapabilities() {
- try {
- ThreadMXBean threadMXBean = Management.getThreadMXBean();
- Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
- } catch (LinkageError err) {
- Assume.assumeNoException("Cannot run without java.management JDK9 module", err);
- }
+ Assume.assumeTrue("skipping management interface test", GraalServices.isCurrentThreadCpuTimeSupported());
}
/**
@@ -63,10 +56,9 @@
* {@code ms}
*/
private static long spin(long ms) {
- ThreadMXBean threadMXBean = Management.getThreadMXBean();
- long start = threadMXBean.getCurrentThreadCpuTime();
+ long start = GraalServices.getCurrentThreadCpuTime();
do {
- long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000;
+ long durationMS = (GraalServices.getCurrentThreadCpuTime() - start) / 1000;
if (durationMS >= ms) {
return durationMS;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.debug;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
class CounterKeyImpl extends AbstractKey implements CounterKey {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -264,9 +264,8 @@
firstSeen.put(o, o);
if (DebugOptions.DumpOnError.getValue(options) || DebugOptions.Dump.getValue(options) != null) {
debug.dump(DebugContext.BASIC_LEVEL, o, "Exception: %s", e);
- } else {
- debug.log("Context obj %s", o);
}
+ debug.log("Context obj %s", o);
}
}
} finally {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Thu Apr 26 17:59:02 2018 +0200
@@ -56,11 +56,12 @@
import java.util.SortedMap;
import java.util.TreeMap;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Pair;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import org.graalvm.graphio.GraphOutput;
import jdk.vm.ci.meta.JavaMethod;
@@ -236,14 +237,15 @@
this.unscopedTimers = parseUnscopedMetricSpec(Timers.getValue(options), "".equals(timeValue), true);
this.unscopedMemUseTrackers = parseUnscopedMetricSpec(MemUseTrackers.getValue(options), "".equals(trackMemUseValue), true);
- if (unscopedTimers != null ||
- unscopedMemUseTrackers != null ||
- timeValue != null ||
- trackMemUseValue != null) {
- try {
- Class.forName("java.lang.management.ManagementFactory");
- } catch (ClassNotFoundException ex) {
- throw new IllegalArgumentException("Time, Timers, MemUseTrackers and TrackMemUse options require java.management module");
+ if (unscopedTimers != null || timeValue != null) {
+ if (!GraalServices.isCurrentThreadCpuTimeSupported()) {
+ throw new IllegalArgumentException("Time and Timers options require VM support for querying CPU time");
+ }
+ }
+
+ if (unscopedMemUseTrackers != null || trackMemUseValue != null) {
+ if (!GraalServices.isThreadAllocatedMemorySupported()) {
+ throw new IllegalArgumentException("MemUseTrackers and TrackMemUse options require VM support for querying thread allocated memory");
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,11 +27,12 @@
import java.nio.file.Path;
import java.nio.file.Paths;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
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;
/**
* Options that configure a {@link DebugContext} and related functionality.
@@ -133,9 +134,7 @@
@Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
- @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug)
- public static final OptionKey<Integer> PrintXmlGraphPort = new OptionKey<>(4444);
- @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug)
+ @Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug)
public static final OptionKey<Integer> PrintBinaryGraphPort = new OptionKey<>(4445);
@Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);
@@ -164,23 +163,10 @@
@Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug)
public static final OptionKey<Boolean> BootstrapInitializeOnly = new OptionKey<>(false);
- // These will be removed at some point
- @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug)
- static final OptionKey<String> PrintIdealGraphAddress = new DebugOptions.DeprecatedOptionKey<>(PrintGraphHost);
- @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug)
- static final OptionKey<Boolean> PrintIdealGraphSchedule = new DebugOptions.DeprecatedOptionKey<>(PrintGraphWithSchedule);
- @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug)
- static final OptionKey<Boolean> PrintIdealGraph = new DebugOptions.DeprecatedOptionKey<>(PrintGraph);
- @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug)
- static final OptionKey<Boolean> PrintIdealGraphFile = new DebugOptions.DeprecatedOptionKey<>(PrintGraphFile);
- @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug)
- static final OptionKey<Integer> PrintIdealGraphPort = new DebugOptions.DeprecatedOptionKey<>(PrintXmlGraphPort);
- // @formatter:on
-
/**
* Gets the directory in which {@link DebugDumpHandler}s can generate output. This will be the
* directory specified by {@link #DumpPath} if it has been set otherwise it will be derived from
- * the default value of {@link #DumpPath} and {@link PathUtilities#getGlobalTimeStamp()}.
+ * the default value of {@link #DumpPath} and {@link GraalServices#getGlobalTimeStamp()}.
*
* This method will ensure the returned directory exists, printing a message to {@link TTY} if
* it creates it.
@@ -193,14 +179,16 @@
if (DumpPath.hasBeenSet(options)) {
dumpDir = Paths.get(DumpPath.getValue(options));
} else {
- dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(PathUtilities.getGlobalTimeStamp()));
+ dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(GraalServices.getGlobalTimeStamp()));
}
dumpDir = dumpDir.toAbsolutePath();
if (!Files.exists(dumpDir)) {
synchronized (DebugConfigImpl.class) {
if (!Files.exists(dumpDir)) {
Files.createDirectories(dumpDir);
- TTY.println("Dumping debug output in %s", dumpDir.toString());
+ if (ShowDumpFiles.getValue(options)) {
+ TTY.println("Dumping debug output in %s", dumpDir.toString());
+ }
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java Thu Apr 26 17:59:02 2018 +0200
@@ -39,6 +39,7 @@
import java.util.zip.ZipOutputStream;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
/**
* Manages a directory into which diagnostics such crash reports and dumps should be written. The
@@ -69,26 +70,6 @@
return getPath(true);
}
- /**
- * Gets a unique identifier for this execution such as a process ID.
- */
- protected String getExecutionID() {
- try {
- String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
- try {
- int index = runtimeName.indexOf('@');
- if (index != -1) {
- long pid = Long.parseLong(runtimeName.substring(0, index));
- return Long.toString(pid);
- }
- } catch (NumberFormatException e) {
- }
- return runtimeName;
- } catch (LinkageError err) {
- return String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
- }
- }
-
private synchronized String getPath(boolean createIfNull) {
if (path == null && createIfNull) {
path = createPath();
@@ -120,7 +101,7 @@
// directory specified by the DumpPath option.
baseDir = Paths.get(".");
}
- return baseDir.resolve("graal_diagnostics_" + getExecutionID()).toAbsolutePath().toString();
+ return baseDir.resolve("graal_diagnostics_" + GraalServices.getExecutionID()).toAbsolutePath().toString();
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,9 +29,9 @@
import java.util.Collections;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
import org.graalvm.compiler.options.OptionValues;
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
/**
* Registry for allocating a globally unique integer id to each {@link AbstractKey}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.debug;
-
-import static java.lang.Thread.currentThread;
-
-public class Management {
-
- private static final com.sun.management.ThreadMXBean threadMXBean = Management.initThreadMXBean();
-
- /**
- * The amount of memory allocated by
- * {@link com.sun.management.ThreadMXBean#getThreadAllocatedBytes(long)} itself.
- */
- private static final long threadMXBeanOverhead = -getCurrentThreadAllocatedBytes() + getCurrentThreadAllocatedBytes();
-
- public static long getCurrentThreadAllocatedBytes() {
- return threadMXBean.getThreadAllocatedBytes(currentThread().getId()) - threadMXBeanOverhead;
- }
-
- private static com.sun.management.ThreadMXBean initThreadMXBean() {
- try {
- return (com.sun.management.ThreadMXBean) java.lang.management.ManagementFactory.getThreadMXBean();
- } catch (Error err) {
- return new UnimplementedBean();
- }
- }
-
- public static java.lang.management.ThreadMXBean getThreadMXBean() {
- return threadMXBean;
- }
-
- private static class UnimplementedBean implements java.lang.management.ThreadMXBean, com.sun.management.ThreadMXBean {
-
- @Override
- public javax.management.ObjectName getObjectName() {
- return null;
- }
-
- @Override
- public long getThreadAllocatedBytes(long arg0) {
- return 0;
- }
-
- @Override
- public long[] getThreadAllocatedBytes(long[] arg0) {
- return null;
- }
-
- @Override
- public long[] getThreadCpuTime(long[] arg0) {
- return null;
- }
-
- @Override
- public long[] getThreadUserTime(long[] arg0) {
- return null;
- }
-
- @Override
- public boolean isThreadAllocatedMemoryEnabled() {
- return false;
- }
-
- @Override
- public boolean isThreadAllocatedMemorySupported() {
- return false;
- }
-
- @Override
- public void setThreadAllocatedMemoryEnabled(boolean arg0) {
- }
-
- @Override
- public int getThreadCount() {
- return 0;
- }
-
- @Override
- public int getPeakThreadCount() {
- return 0;
- }
-
- @Override
- public long getTotalStartedThreadCount() {
- return 0;
- }
-
- @Override
- public int getDaemonThreadCount() {
- return 0;
- }
-
- @Override
- public long[] getAllThreadIds() {
- return null;
- }
-
- @Override
- public java.lang.management.ThreadInfo getThreadInfo(long id) {
- return null;
- }
-
- @Override
- public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids) {
- return null;
- }
-
- @Override
- public java.lang.management.ThreadInfo getThreadInfo(long id, int maxDepth) {
- return null;
- }
-
- @Override
- public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
- return null;
- }
-
- @Override
- public boolean isThreadContentionMonitoringSupported() {
- return false;
- }
-
- @Override
- public boolean isThreadContentionMonitoringEnabled() {
- return false;
- }
-
- @Override
- public void setThreadContentionMonitoringEnabled(boolean enable) {
- }
-
- @Override
- public long getCurrentThreadCpuTime() {
- return 0;
- }
-
- @Override
- public long getCurrentThreadUserTime() {
- return 0;
- }
-
- @Override
- public long getThreadCpuTime(long id) {
- return 0;
- }
-
- @Override
- public long getThreadUserTime(long id) {
- return 0;
- }
-
- @Override
- public boolean isThreadCpuTimeSupported() {
- return false;
- }
-
- @Override
- public boolean isCurrentThreadCpuTimeSupported() {
- return false;
- }
-
- @Override
- public boolean isThreadCpuTimeEnabled() {
- return false;
- }
-
- @Override
- public void setThreadCpuTimeEnabled(boolean enable) {
- }
-
- @Override
- public long[] findMonitorDeadlockedThreads() {
- return null;
- }
-
- @Override
- public void resetPeakThreadCount() {
- }
-
- @Override
- public long[] findDeadlockedThreads() {
- return null;
- }
-
- @Override
- public boolean isObjectMonitorUsageSupported() {
- return false;
- }
-
- @Override
- public boolean isSynchronizerUsageSupported() {
- return false;
- }
-
- @Override
- public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
- return null;
- }
-
- @Override
- public java.lang.management.ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
- return null;
- }
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.debug;
+import org.graalvm.compiler.serviceprovider.GraalServices;
+
/**
* Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility
* should be employed using the try-with-resources pattern:
@@ -52,6 +54,6 @@
MemUseTrackerKey doc(String string);
static long getCurrentThreadAllocatedBytes() {
- return Management.getCurrentThreadAllocatedBytes();
+ return GraalServices.getCurrentThreadAllocatedBytes();
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
class MemUseTrackerKeyImpl extends AccumulatedKey implements MemUseTrackerKey {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.Comparator;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
/**
* A key for a metric.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,6 @@
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.concurrent.atomic.AtomicLong;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
@@ -39,19 +38,6 @@
*/
public class PathUtilities {
- private static final AtomicLong globalTimeStamp = new AtomicLong();
-
- /**
- * Gets a time stamp for the current process. This method will always return the same value for
- * the current VM execution.
- */
- public static long getGlobalTimeStamp() {
- if (globalTimeStamp.get() == 0) {
- globalTimeStamp.compareAndSet(0, System.currentTimeMillis());
- }
- return globalTimeStamp.get();
- }
-
/**
* Gets a value based on {@code name} that can be passed to {@link Paths#get(String, String...)}
* without causing an {@link InvalidPathException}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,21 +22,13 @@
*/
package org.graalvm.compiler.debug;
+import org.graalvm.compiler.serviceprovider.GraalServices;
+
/**
* A consistent source of timing data that should be used by all facilities in the debug package.
*/
public class TimeSource {
- private static final boolean USING_BEAN;
- private static final java.lang.management.ThreadMXBean threadMXBean;
-
- static {
- threadMXBean = Management.getThreadMXBean();
- if (threadMXBean.isThreadCpuTimeSupported()) {
- USING_BEAN = true;
- } else {
- USING_BEAN = false;
- }
- }
+ private static final boolean USING_THREAD_CPU_TIME = GraalServices.isCurrentThreadCpuTimeSupported();
/**
* Gets the current time of this thread in nanoseconds from the most accurate timer available on
@@ -50,7 +42,7 @@
* @return the current thread's time in nanoseconds
*/
public static long getTimeNS() {
- return USING_BEAN ? threadMXBean.getCurrentThreadCpuTime() : System.nanoTime();
+ return USING_THREAD_CPU_TIME ? GraalServices.getCurrentThreadCpuTime() : System.nanoTime();
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
import java.util.concurrent.TimeUnit;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
final class TimerKeyImpl extends AccumulatedKey implements TimerKey {
static class FlatTimer extends AbstractKey implements TimerKey {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
- This configuration file was written by the eclipse-cs plugin configuration editor
--->
-<!--
- Checkstyle-Configuration: Checks
- Description: none
--->
-<module name="Checker">
- <property name="severity" value="error"/>
- <module name="TreeWalker">
- <module name="AvoidStarImport">
- <property name="allowClassImports" value="false"/>
- <property name="allowStaticMemberImports" value="false"/>
- </module>
- <property name="tabWidth" value="4"/>
- <module name="FileContentsHolder"/>
- <module name="JavadocStyle">
- <property name="checkHtml" value="false"/>
- </module>
- <module name="LocalFinalVariableName"/>
- <module name="LocalVariableName"/>
- <module name="MemberName">
- <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
- </module>
- <module name="MethodName"/>
- <module name="PackageName"/>
- <module name="ParameterName"/>
- <module name="TypeName">
- <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
- </module>
- <module name="RedundantImport"/>
- <module name="LineLength">
- <property name="max" value="250"/>
- </module>
- <module name="MethodParamPad"/>
- <module name="NoWhitespaceAfter">
- <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
- </module>
- <module name="NoWhitespaceBefore">
- <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
- </module>
- <module name="ParenPad"/>
- <module name="TypecastParenPad">
- <property name="tokens" value="RPAREN,TYPECAST"/>
- </module>
- <module name="WhitespaceAfter"/>
- <module name="WhitespaceAround">
- <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
- </module>
- <module name="RedundantModifier"/>
- <module name="AvoidNestedBlocks">
- <property name="allowInSwitchCase" value="true"/>
- </module>
- <module name="EmptyBlock">
- <property name="option" value="text"/>
- <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
- </module>
- <module name="LeftCurly"/>
- <module name="NeedBraces"/>
- <module name="RightCurly"/>
- <module name="EmptyStatement"/>
- <module name="HiddenField">
- <property name="severity" value="ignore"/>
- <property name="ignoreConstructorParameter" value="true"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="FinalClass"/>
- <module name="HideUtilityClassConstructor">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="ArrayTypeStyle"/>
- <module name="UpperEll"/>
- <module name="FallThrough"/>
- <module name="FinalLocalVariable">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="MultipleVariableDeclarations"/>
- <module name="StringLiteralEquality">
- <property name="severity" value="error"/>
- </module>
- <module name="SuperFinalize"/>
- <module name="UnnecessaryParentheses">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="Indentation">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="StaticVariableName">
- <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
- </module>
- <module name="EmptyForInitializerPad"/>
- <module name="EmptyForIteratorPad"/>
- <module name="ModifierOrder"/>
- <module name="DefaultComesLast"/>
- <module name="InnerAssignment">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="ModifiedControlVariable"/>
- <module name="MutableException">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="ParameterAssignment">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="RegexpSinglelineJava">
- <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
- <property name="format" value="\s$"/>
- <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
- <property name="ignoreComments" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
- </module>
- <module name="RegexpSinglelineJava">
- <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
- <property name="format" value=" ,"/>
- <property name="message" value="illegal space before a comma"/>
- <property name="ignoreComments" value="true"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="[^\x00-\x7F]"/>
- <property name="message" value="Only use ASCII characters."/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
- <property name="message" value="Don't use old synchronized collection classes"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="instanceof MoveOp"/>
- <property name="message" value="Do not use `op instanceof MoveOp`. Use `MoveOp.isMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="instanceof ValueMoveOp"/>
- <property name="message" value="Do not use `op instanceof ValueMoveOp`. Use `ValueMoveOp.isValueMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="instanceof LoadConstantOp"/>
- <property name="message" value="Do not use `op instanceof LoadConstantOp`. Use `LoadConstantOp.isLoadConstantOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="\(MoveOp\)"/>
- <property name="message" value="Do not cast directly to `MoveOp`. Use `MoveOp.asMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="\(ValueMoveOp\)"/>
- <property name="message" value="Do not cast directly to `ValueMoveOp`. Use `ValueMoveOp.asValueMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="\(LoadConstantOp\)"/>
- <property name="message" value="Do not cast directly to `LoadConstantOp`. Use `LoadConstantOp.asLoadConstantOp(op)` instead!"/>
- </module>
- </module>
- <module name="RegexpHeader">
- <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates\. All rights reserved\.\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], .*\. All rights reserved\.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation\.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE\. See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\)\.\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc\., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www\.oracle\.com if you need additional information or have any\n \* questions\.\n \*/\n"/>
- <property name="multiLines" value="3"/>
- <property name="fileExtensions" value="java"/>
- </module>
- <module name="FileTabCharacter">
- <property name="severity" value="error"/>
- <property name="fileExtensions" value="java"/>
- </module>
- <module name="NewlineAtEndOfFile">
- <property name="lineSeparator" value="lf"/>
- </module>
- <module name="Translation"/>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
- <property name="checkFormat" value="ConstantNameCheck"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
- <property name="checkFormat" value="MethodName"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
- <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
- <property name="checkFormat" value="ParameterAssignment"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
- <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
- <property name="checkFormat" value="FinalLocalVariable"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop"/>
- <property name="onCommentFormat" value="Checkstyle: resume"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
- <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
- <property name="checkFormat" value="InnerAssignment"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
- <property name="checkFormat" value="MemberName"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
- </module>
- <module name="RegexpMultiline">
- <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
- <property name="format" value="\r\n"/>
- <property name="message" value="illegal Windows line ending"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop header check"/>
- <property name="onCommentFormat" value="CheckStyle: resume header check"/>
- <property name="checkFormat" value=".*Header"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
- <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
- <property name="checkFormat" value="LineLength"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: start generated"/>
- <property name="onCommentFormat" value="CheckStyle: stop generated"/>
- <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
- </module>
-</module>
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.function.Consumer;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
/**
* This class is a container of a graph that needs to be readonly and optionally a lazily created
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.graph;
+import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeInsertion;
import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.Default;
import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.Track;
import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.UpdateOnly;
@@ -33,15 +34,16 @@
import java.util.Iterator;
import java.util.function.Consumer;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TimerKey;
+import org.graalvm.compiler.graph.Node.NodeInsertionStackTrace;
import org.graalvm.compiler.graph.Node.ValueNumberable;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.options.Option;
@@ -49,6 +51,8 @@
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
/**
* This class is a graph container, it contains the set of nodes that belong to this graph.
*/
@@ -195,7 +199,7 @@
* was opened
*/
public DebugCloseable withNodeSourcePosition(Node node) {
- return withNodeSourcePosition(node.sourcePosition);
+ return withNodeSourcePosition(node.getNodeSourcePosition());
}
/**
@@ -719,6 +723,9 @@
assert node.getNodeClass().valueNumberable();
T other = this.findDuplicate(node);
if (other != null) {
+ if (other.getNodeSourcePosition() == null) {
+ other.setNodeSourcePosition(node.getNodeSourcePosition());
+ }
return other;
} else {
T result = addHelper(node);
@@ -1097,6 +1104,9 @@
if (currentNodeSourcePosition != null && trackNodeSourcePosition()) {
node.setNodeSourcePosition(currentNodeSourcePosition);
}
+ if (TrackNodeInsertion.getValue(getOptions())) {
+ node.setInsertionPosition(new NodeInsertionStackTrace());
+ }
updateNodeCaches(node);
@@ -1189,6 +1199,23 @@
return true;
}
+ public boolean verifySourcePositions() {
+ if (trackNodeSourcePosition()) {
+ ResolvedJavaMethod root = null;
+ for (Node node : getNodes()) {
+ NodeSourcePosition pos = node.getNodeSourcePosition();
+ if (pos != null) {
+ if (root == null) {
+ root = pos.getRootMethod();
+ } else {
+ assert pos.verifyRootMethod(root) : node;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
public Node getNode(int id) {
return nodes[id];
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,7 @@
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Formattable;
@@ -84,7 +85,8 @@
public abstract class Node implements Cloneable, Formattable, NodeInterface {
public static final NodeClass<?> TYPE = null;
- public static final boolean USE_UNSAFE_TO_CLONE = true;
+
+ public static final boolean TRACK_CREATION_POSITION = Boolean.getBoolean("debug.graal.TrackNodeCreationPosition");
static final int DELETED_ID_START = -1000000000;
static final int INITIAL_ID = -1;
@@ -230,6 +232,40 @@
public static final int NODE_LIST = -2;
public static final int NOT_ITERABLE = -1;
+ static class NodeStackTrace {
+ final StackTraceElement[] stackTrace;
+
+ NodeStackTrace() {
+ this.stackTrace = new Throwable().getStackTrace();
+ }
+
+ private String getString(String label) {
+ StringBuilder sb = new StringBuilder();
+ if (label != null) {
+ sb.append(label).append(": ");
+ }
+ for (StackTraceElement ste : stackTrace) {
+ sb.append("at ").append(ste.toString()).append('\n');
+ }
+ return sb.toString();
+ }
+
+ String getStrackTraceString() {
+ return getString(null);
+ }
+
+ @Override
+ public String toString() {
+ return getString(getClass().getSimpleName());
+ }
+ }
+
+ static class NodeCreationStackTrace extends NodeStackTrace {
+ }
+
+ static class NodeInsertionStackTrace extends NodeStackTrace {
+ }
+
public Node(NodeClass<? extends Node> c) {
init(c);
}
@@ -239,6 +275,9 @@
this.nodeClass = c;
id = INITIAL_ID;
extraUsages = NO_NODES;
+ if (TRACK_CREATION_POSITION) {
+ setCreationPosition(new NodeCreationStackTrace());
+ }
}
final int id() {
@@ -577,32 +616,95 @@
}
/**
- * The position of the bytecode that generated this node.
+ * Information associated with this node. A single value is stored directly in the field.
+ * Multiple values are stored by creating an Object[].
*/
- NodeSourcePosition sourcePosition;
+ private Object annotation;
+
+ private <T> T getNodeInfo(Class<T> clazz) {
+ assert clazz != Object[].class;
+ if (annotation == null) {
+ return null;
+ }
+ if (clazz.isInstance(annotation)) {
+ return clazz.cast(annotation);
+ }
+ if (annotation.getClass() == Object[].class) {
+ Object[] annotations = (Object[]) annotation;
+ for (Object ann : annotations) {
+ if (clazz.isInstance(ann)) {
+ return clazz.cast(ann);
+ }
+ }
+ }
+ return null;
+ }
+
+ private <T> void setNodeInfo(Class<T> clazz, T value) {
+ assert clazz != Object[].class;
+ if (annotation == null || clazz.isInstance(annotation)) {
+ // Replace the current value
+ this.annotation = value;
+ } else if (annotation.getClass() == Object[].class) {
+ Object[] annotations = (Object[]) annotation;
+ for (int i = 0; i < annotations.length; i++) {
+ if (clazz.isInstance(annotations[i])) {
+ annotations[i] = value;
+ return;
+ }
+ }
+ Object[] newAnnotations = Arrays.copyOf(annotations, annotations.length + 1);
+ newAnnotations[annotations.length] = value;
+ this.annotation = newAnnotations;
+ } else {
+ this.annotation = new Object[]{this.annotation, value};
+ }
+ }
/**
* Gets the source position information for this node or null if it doesn't exist.
*/
public NodeSourcePosition getNodeSourcePosition() {
- return sourcePosition;
+ return getNodeInfo(NodeSourcePosition.class);
}
/**
- * Set the source position to {@code sourcePosition}.
+ * Set the source position to {@code sourcePosition}. Setting it to null is ignored so that it's
+ * not accidentally cleared. Use {@link #clearNodeSourcePosition()} instead.
*/
public void setNodeSourcePosition(NodeSourcePosition sourcePosition) {
- assert sourcePosition != null || this.sourcePosition == null || this.sourcePosition.isPlaceholder() : "Invalid source position at node with id " + id;
- this.sourcePosition = sourcePosition;
- // assert sourcePosition == null || graph == null || graph.trackNodeSourcePosition;
+ if (sourcePosition == null) {
+ return;
+ }
+ setNodeInfo(NodeSourcePosition.class, sourcePosition);
+ }
+
+ public void clearNodeSourcePosition() {
+ setNodeInfo(NodeSourcePosition.class, null);
+ }
+
+ public NodeCreationStackTrace getCreationPosition() {
+ return getNodeInfo(NodeCreationStackTrace.class);
+ }
+
+ public void setCreationPosition(NodeCreationStackTrace trace) {
+ setNodeInfo(NodeCreationStackTrace.class, trace);
+ }
+
+ public NodeInsertionStackTrace getInsertionPosition() {
+ return getNodeInfo(NodeInsertionStackTrace.class);
+ }
+
+ public void setInsertionPosition(NodeInsertionStackTrace trace) {
+ setNodeInfo(NodeInsertionStackTrace.class, trace);
}
/**
* Update the source position only if it is null.
*/
public void updateNodeSourcePosition(Supplier<NodeSourcePosition> sourcePositionSupp) {
- if (this.sourcePosition == null) {
+ if (this.getNodeSourcePosition() == null) {
setNodeSourcePosition(sourcePositionSupp.get());
}
}
@@ -919,8 +1021,8 @@
}
newNode.graph = into;
newNode.id = INITIAL_ID;
- if (sourcePosition != null && (into == null || into.updateNodeSourcePosition())) {
- newNode.setNodeSourcePosition(sourcePosition);
+ if (getNodeSourcePosition() != null && (into == null || into.updateNodeSourcePosition())) {
+ newNode.setNodeSourcePosition(getNodeSourcePosition());
}
if (into != null) {
into.register(newNode);
@@ -1077,6 +1179,14 @@
if (pos != null) {
map.put("nodeSourcePosition", pos);
}
+ NodeCreationStackTrace creation = getCreationPosition();
+ if (creation != null) {
+ map.put("nodeCreationPosition", creation.getStrackTraceString());
+ }
+ NodeInsertionStackTrace insertion = getInsertionPosition();
+ if (insertion != null) {
+ map.put("nodeInsertionPosition", insertion.getStrackTraceString());
+ }
return map;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,8 +42,8 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.FieldIntrospection;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.FieldsScanner;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.util.Iterator;
import java.util.function.BiFunction;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
public class NodeMap<T> extends NodeIdAccessor implements EconomicMap<Node, T> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java Thu Apr 26 17:59:02 2018 +0200
@@ -64,6 +64,21 @@
return this;
}
+ public ResolvedJavaMethod getRootMethod() {
+ NodeSourcePosition cur = this;
+ while (cur.getCaller() != null) {
+ cur = cur.getCaller();
+ }
+ return cur.getMethod();
+ }
+
+ public boolean verifyRootMethod(ResolvedJavaMethod root) {
+ JavaMethod currentRoot = getRootMethod();
+ assert root.equals(currentRoot) || root.getName().equals(currentRoot.getName()) && root.getSignature().toMethodDescriptor().equals(currentRoot.getSignature().toMethodDescriptor()) &&
+ root.getDeclaringClass().getName().equals(currentRoot.getDeclaringClass().getName()) : root + " " + currentRoot;
+ return true;
+ }
+
enum Marker {
None,
Placeholder,
@@ -107,11 +122,11 @@
}
public static NodeSourcePosition substitution(ResolvedJavaMethod method) {
- return new NodeSourcePosition(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Substitution);
+ return substitution(null, method);
}
- public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
- return new NodeSourcePosition(caller, method, bci, Substitution);
+ public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method) {
+ return new NodeSourcePosition(caller, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Substitution);
}
public boolean isSubstitution() {
@@ -151,7 +166,7 @@
return d;
}
- public SourceLanguagePosition getSourceLanauage() {
+ public SourceLanguagePosition getSourceLanguage() {
return sourceLanguagePosition;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePosition.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePosition.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.graph;
-import java.util.Map;
+import java.net.URI;
/**
* Provides a path to report information about a high level language source position to the Graph
@@ -31,14 +31,22 @@
public interface SourceLanguagePosition {
/**
- * This is called during dumping of Nodes. The implementation should add any properties which
- * describe this source position. The actual keys and values used are a private contract between
- * the language implementation and the Graph Visualizer.
- */
- void addSourceInformation(Map<String, Object> props);
-
- /**
* Produce a compact description of this position suitable for printing.
*/
String toShortString();
+
+ /** Mimics GraphLocations operation. */
+ int getOffsetEnd();
+
+ /** Mimics GraphLocations operation. */
+ int getOffsetStart();
+
+ /** Mimics GraphLocations operation. */
+ int getLineNumber();
+
+ /** Mimics GraphLocations operation. */
+ URI getURI();
+
+ /** Mimics GraphLocations operation. */
+ String getLanguage();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp;
import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.aarch64.AArch64Address;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
+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;
@@ -50,7 +51,11 @@
import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
+import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.Phase;
+import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins;
@@ -77,7 +82,7 @@
@Override
public String getName() {
- return "core";
+ return "community";
}
@Override
@@ -141,7 +146,7 @@
replacements.setGraphBuilderPlugins(plugins);
}
try (InitTimer rt = timer("create Suites provider")) {
- suites = createSuites(config, graalRuntime, compilerConfiguration, plugins);
+ suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, replacements);
}
providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
snippetReflection, wordTypes,
@@ -178,8 +183,11 @@
return new AArch64HotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
}
- protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins) {
- return new AArch64HotSpotSuitesProvider(new AArch64SuitesCreator(compilerConfiguration, plugins), config, runtime, new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
+ protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
+ @SuppressWarnings("unused") Replacements replacements) {
+ AArch64SuitesCreator suitesCreator = new AArch64SuitesCreator(compilerConfiguration, plugins, SchedulePhase.class);
+ Phase addressLoweringPhase = new AddressLoweringByUsePhase(new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
+ return new AddressLoweringHotSpotSuitesProvider(suitesCreator, config, runtime, addressLoweringPhase);
}
protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue;
@@ -68,11 +69,12 @@
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
leaveFrame(crb, masm, /* emitSafepoint */false);
- if (System.getProperty("java.specification.version").compareTo("1.8") < 0) {
+ if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) {
// Restore sp from fp if the exception PC is a method handle call site.
try (ScratchRegister sc = masm.getScratchRegister()) {
Register scratch = sc.getRegister();
- AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, /* allowOverwrite */false);
+ final boolean allowOverwrite = false;
+ AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, allowOverwrite);
masm.ldr(32, scratch, address);
Label noRestore = new Label();
masm.cbz(32, scratch, noRestore);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,6 @@
import static jdk.vm.ci.aarch64.AArch64.r24;
import static jdk.vm.ci.aarch64.AArch64.r25;
import static jdk.vm.ci.aarch64.AArch64.r26;
-import static jdk.vm.ci.aarch64.AArch64.r27;
import static jdk.vm.ci.aarch64.AArch64.r28;
import static jdk.vm.ci.aarch64.AArch64.r3;
import static jdk.vm.ci.aarch64.AArch64.r4;
@@ -100,7 +99,7 @@
r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15,
r16, r17, r18, r19, r20, r21, r22, r23,
- r24, r25, r26, r27, r28, /* r29, r30, r31 */
+ r24, r25, r26, /* r27, */ r28, /* r29, r30, r31 */
v0, v1, v2, v3, v4, v5, v6, v7,
v8, v9, v10, v11, v12, v13, v14, v15,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, 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.aarch64;
-
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
-import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
-import org.graalvm.compiler.phases.common.ExpandLogicPhase;
-import org.graalvm.compiler.phases.common.FixReadsPhase;
-import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
-import org.graalvm.compiler.phases.tiers.LowTierContext;
-import org.graalvm.compiler.phases.tiers.Suites;
-import org.graalvm.compiler.phases.tiers.SuitesCreator;
-import org.graalvm.compiler.replacements.aarch64.AArch64ReadReplacementPhase;
-
-import java.util.ListIterator;
-
-/**
- * Subclass to factor out management of address lowering.
- */
-public class AArch64HotSpotSuitesProvider extends HotSpotSuitesProvider {
-
- private final AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse;
-
- public AArch64HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime,
- AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse) {
- super(defaultSuitesCreator, config, runtime);
- this.addressLoweringByUse = addressLoweringByUse;
- }
-
- @Override
- public Suites createSuites(OptionValues options) {
- Suites suites = super.createSuites(options);
-
- ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class);
- if (findPhase == null) {
- findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class);
- }
- findPhase.add(new AddressLoweringByUsePhase(addressLoweringByUse));
-
- findPhase = suites.getLowTier().findPhase(PropagateDeoptimizeProbabilityPhase.class);
- findPhase.add(new AArch64ReadReplacementPhase());
-
- return suites;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.core.amd64.AMD64AddressNode;
import org.graalvm.compiler.core.amd64.AMD64CompressAddressLowering;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -52,6 +52,7 @@
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.OptionValues;
+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.amd64.AMD64GraphBuilderPlugins;
@@ -77,7 +78,7 @@
@Override
public String getName() {
- return "core";
+ return "community";
}
@Override
@@ -186,7 +187,7 @@
protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
HotSpotRegistersProvider registers, Replacements replacements, OptionValues options) {
return new AddressLoweringHotSpotSuitesProvider(new AMD64HotSpotSuitesCreator(compilerConfiguration, plugins), config, runtime,
- new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options));
+ new AddressLoweringPhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options)));
}
protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,6 +33,7 @@
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue;
@@ -68,7 +69,7 @@
// Discard the return address, thus completing restoration of caller frame
masm.incrementq(rsp, 8);
- if (System.getProperty("java.specification.version").compareTo("1.8") < 0) {
+ if (GraalServices.JAVA_SPECIFICATION_VERSION < 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.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java Thu Apr 26 17:59:02 2018 +0200
@@ -46,9 +46,9 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.sparc.SPARCAddress;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -49,6 +49,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.Replacements;
+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;
@@ -72,7 +73,7 @@
@Override
public String getName() {
- return "core";
+ return "community";
}
@Override
@@ -125,7 +126,7 @@
*/
protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
Replacements replacements) {
- return new AddressLoweringHotSpotSuitesProvider(new SPARCSuitesCreator(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering());
+ return new AddressLoweringHotSpotSuitesProvider(new SPARCSuitesCreator(compilerConfiguration, plugins), config, runtime, new AddressLoweringPhase(new SPARCAddressLowering()));
}
protected SPARCHotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
import java.util.TreeSet;
import java.util.stream.Collectors;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -43,7 +43,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
import org.graalvm.compiler.runtime.RuntimeProvider;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import org.graalvm.compiler.test.GraalTest;
import org.junit.Test;
@@ -542,11 +542,11 @@
}
private static boolean isJDK9OrHigher() {
- return JDK9Method.JAVA_SPECIFICATION_VERSION >= 9;
+ return GraalServices.JAVA_SPECIFICATION_VERSION >= 9;
}
private static boolean isJDK10OrHigher() {
- return JDK9Method.JAVA_SPECIFICATION_VERSION >= 10;
+ return GraalServices.JAVA_SPECIFICATION_VERSION >= 10;
}
private static String getHostArchitectureName() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -105,7 +105,6 @@
public void testVMCompilation3() throws IOException, InterruptedException {
final int maxProblems = 4;
Probe[] probes = {
- new Probe("To capture more information for diagnosing or reporting a compilation", maxProblems),
new Probe("Retrying compilation of", maxProblems) {
@Override
String test() {
@@ -131,6 +130,7 @@
testHelper(Collections.emptyList(),
Arrays.asList(
"-Dgraal.CompilationFailureAction=ExitVM",
+ "-Dgraal.TrufflePerformanceWarningsAreFatal=true",
"-Dgraal.CrashAt=root test1"),
"org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
}
@@ -151,6 +151,22 @@
"org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
}
+ /**
+ * Tests that TrufflePerformanceWarningsAreFatal generates diagnostic output.
+ */
+ @Test
+ public void testTruffleCompilation3() throws IOException, InterruptedException {
+ Probe[] probes = {
+ new Probe("Exiting VM due to TrufflePerformanceWarningsAreFatal=true", 1),
+ };
+ testHelper(Arrays.asList(probes),
+ Arrays.asList(
+ "-Dgraal.CompilationFailureAction=Silent",
+ "-Dgraal.TrufflePerformanceWarningsAreFatal=true",
+ "-Dgraal.CrashAt=root test1:PermanentBailout"),
+ "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
+ }
+
private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose");
private static void testHelper(List<Probe> initialProbes, List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
@@ -225,7 +241,7 @@
Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc));
}
if (cfg == 0) {
- Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries));
+ Assert.fail(String.format("Expected at least one .cfg file in %s: %s%n%s", diagnosticOutputZip, entries, proc));
}
} finally {
zip.delete();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
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.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import java.io.Closeable;
import java.io.File;
@@ -66,10 +66,12 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.bytecode.Bytecodes;
import org.graalvm.compiler.core.CompilerThreadFactory;
@@ -86,7 +88,7 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
@@ -107,8 +109,8 @@
/**
* Magic token to denote that JDK classes are to be compiled. If
- * {@link JDK9Method#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled. Otherwise
- * the classes in the Java runtime image are compiled.
+ * {@link GraalServices#Java8OrEarlier}, then 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";
@@ -379,6 +381,11 @@
return new URLClassLoader(new URL[]{url});
}
+ /**
+ * @see "https://docs.oracle.com/javase/9/docs/specs/jar/jar.html#Multi-release"
+ */
+ static Pattern MultiReleaseJarVersionedClassRE = Pattern.compile("META-INF/versions/[1-9][0-9]*/(.+)");
+
@Override
public List<String> getClassNames() throws IOException {
Enumeration<JarEntry> e = jarFile.entries();
@@ -389,6 +396,17 @@
continue;
}
String className = je.getName().substring(0, je.getName().length() - ".class".length());
+ if (className.equals("module-info")) {
+ continue;
+ }
+ if (className.startsWith("META-INF/versions/")) {
+ Matcher m = MultiReleaseJarVersionedClassRE.matcher(className);
+ if (m.matches()) {
+ className = m.group(1);
+ } else {
+ continue;
+ }
+ }
classNames.add(className.replace('/', '.'));
}
return classNames;
@@ -562,6 +580,10 @@
continue;
}
+ if (!isClassIncluded(className)) {
+ continue;
+ }
+
try {
// Load and initialize class
Class<?> javaClass = Class.forName(className, true, loader);
@@ -581,14 +603,6 @@
continue;
}
- /*
- * Only check filters after class loading and resolution to mitigate impact
- * on reproducibility.
- */
- if (!isClassIncluded(className)) {
- continue;
- }
-
// Are we compiling this class?
MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
if (classFileCounter >= startAt) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,6 @@
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
-import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Collection;
@@ -32,7 +31,7 @@
import java.util.HashSet;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.phases.HighTier;
import org.graalvm.compiler.debug.DebugContext;
@@ -41,6 +40,7 @@
import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.BeforeClass;
@@ -58,11 +58,6 @@
@BeforeClass
public static void checkVMArguments() {
- try {
- Class.forName("java.lang.management.ManagementFactory");
- } catch (ClassNotFoundException ex) {
- Assume.assumeNoException("cannot check for monitors without java.management JDK9 module", ex);
- }
/*
* Note: The -Xcomp execution mode of the VM will stop most of the OSR test cases from
* working as every method is compiled at level3 (followed by level4 on the second
@@ -71,8 +66,8 @@
* installed nmethod at a given BCI.
*
*/
- RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
- List<String> arguments = runtimeMxBean.getInputArguments();
+ List<String> arguments = GraalServices.getInputArguments();
+ Assume.assumeTrue("cannot check for monitors without", arguments != null);
for (String arg : arguments) {
Assume.assumeFalse(arg.equals(COMPILE_ONLY_FLAG));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,9 @@
import org.junit.Assert;
import org.junit.Test;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
/**
* Test on-stack-replacement with Graal. The test manually triggers a Graal OSR-compilation which is
* later invoked when hitting the backedge counter overflow.
@@ -99,4 +102,57 @@
return ret;
}
+ @Test
+ public void testOSR04() {
+ testFunnyOSR("testDoWhile", GraalOSRTest::testDoWhile);
+ }
+
+ @Test
+ public void testOSR05() {
+ testFunnyOSR("testDoWhileLocked", GraalOSRTest::testDoWhileLocked);
+ }
+
+ /**
+ * Because of a bug in C1 profile collection HotSpot can sometimes request an OSR compilation
+ * for a backedge which isn't ever taken. This test synthetically creates that situation.
+ */
+ private void testFunnyOSR(String name, Runnable warmup) {
+ ResolvedJavaMethod method = getResolvedJavaMethod(name);
+ int iterations = 0;
+ while (true) {
+ ProfilingInfo profilingInfo = method.getProfilingInfo();
+ if (profilingInfo.isMature()) {
+ break;
+ }
+
+ warmup.run();
+ if (iterations++ % 1000 == 0) {
+ System.err.print('.');
+ }
+ if (iterations > 200000) {
+ throw new AssertionError("no profile");
+ }
+ }
+ compileOSR(getInitialOptions(), method);
+ Result result = executeExpected(method, null);
+ checkResult(result);
+ }
+
+ private static boolean repeatLoop;
+
+ public static ReturnValue testDoWhile() {
+ do {
+ sideEffect++;
+ } while (repeatLoop);
+ return ReturnValue.SUCCESS;
+ }
+
+ public static synchronized ReturnValue testDoWhileLocked() {
+ // synchronized (GraalOSRTest.class) {
+ do {
+ sideEffect++;
+ } while (repeatLoop);
+ // }
+ return ReturnValue.SUCCESS;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,8 @@
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.bytecode.BytecodeStream;
import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
+import org.graalvm.compiler.core.GraalCompilerOptions;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
@@ -95,18 +97,18 @@
* Returns the target BCI of the first bytecode backedge. This is where HotSpot triggers
* on-stack-replacement in case the backedge counter overflows.
*/
- private static int getBackedgeBCI(DebugContext debug, ResolvedJavaMethod method) {
+ static int getBackedgeBCI(DebugContext debug, ResolvedJavaMethod method) {
Bytecode code = new ResolvedJavaMethodBytecode(method);
BytecodeStream stream = new BytecodeStream(code.getCode());
OptionValues options = debug.getOptions();
BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code, options, debug);
for (BciBlock block : bciBlockMapping.getBlocks()) {
- if (block.startBci != -1) {
- int bci = block.startBci;
+ if (block.getStartBci() != -1) {
+ int bci = block.getEndBci();
for (BciBlock succ : block.getSuccessors()) {
- if (succ.startBci != -1) {
- int succBci = succ.startBci;
+ if (succ.getStartBci() != -1) {
+ int succBci = succ.getStartBci();
if (succBci < bci) {
// back edge
return succBci;
@@ -120,16 +122,22 @@
return -1;
}
- private static void checkResult(Result result) {
+ protected static void checkResult(Result result) {
Assert.assertNull("Unexpected exception", result.exception);
Assert.assertNotNull(result.returnValue);
Assert.assertTrue(result.returnValue instanceof ReturnValue);
Assert.assertEquals(ReturnValue.SUCCESS, result.returnValue);
}
- private void compileOSR(OptionValues options, ResolvedJavaMethod method) {
+ protected void compileOSR(OptionValues options, ResolvedJavaMethod method) {
+ OptionValues goptions = options;
+ // Silence diagnostics for permanent bailout errors as they
+ // are expected for some OSR tests.
+ if (!GraalCompilerOptions.CompilationBailoutAction.hasBeenSet(options)) {
+ goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAction, ExceptionAction.Silent);
+ }
// ensure eager resolving
- StructuredGraph graph = parseEager(method, AllowAssumptions.YES, options);
+ StructuredGraph graph = parseEager(method, AllowAssumptions.YES, goptions);
DebugContext debug = graph.getDebug();
int bci = getBackedgeBCI(debug, method);
assert bci != -1;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.lang.management.ManagementFactory;
-import java.lang.reflect.Field;
-import java.util.Arrays;
-
-import javax.management.Attribute;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanInfo;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanServer;
-import javax.management.ObjectInstance;
-import javax.management.ObjectName;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.hotspot.HotSpotGraalMBean;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.test.GraalTest;
-import org.junit.Assume;
-import org.junit.Test;
-
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-public class HotSpotGraalMBeanTest {
-
- public HotSpotGraalMBeanTest() {
- // No support for registering Graal MBean yet on JDK9 (GR-4025). We cannot
- // rely on an exception being thrown when accessing ManagementFactory.platformMBeanServer
- // via reflection as recent JDK9 changes now allow this and issue a warning instead.
- Assume.assumeTrue(GraalTest.Java8OrEarlier);
- }
-
- @Test
- public void registration() throws Exception {
- ObjectName name;
-
- Field field = null;
- try {
- field = stopMBeanServer();
- } catch (Exception ex) {
- if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
- // skip on JDK9
- return;
- }
- }
- assertNull("The platformMBeanServer isn't initialized now", field.get(null));
-
- HotSpotGraalMBean bean = HotSpotGraalMBean.create(null);
- assertNotNull("Bean created", bean);
-
- assertNull("It is not registered yet", bean.ensureRegistered(true));
-
- MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
- assertNotNull("Now the bean thinks it is registered", name = bean.ensureRegistered(true));
-
- assertNotNull("And the bean is found", server.getObjectInstance(name));
- }
-
- private static Field stopMBeanServer() throws NoSuchFieldException, SecurityException, IllegalAccessException, IllegalArgumentException {
- final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
- field.setAccessible(true);
- field.set(null, null);
- return field;
- }
-
- @Test
- public void readBeanInfo() throws Exception {
- ObjectName name;
-
- assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
-
- HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
- assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
- final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
- ObjectInstance bean = server.getObjectInstance(name);
- assertNotNull("Bean is registered", bean);
- MBeanInfo info = server.getMBeanInfo(name);
- assertNotNull("Info is found", info);
-
- MBeanAttributeInfo printCompilation = (MBeanAttributeInfo) findAttributeInfo("PrintCompilation", info);
- assertNotNull("PrintCompilation found", printCompilation);
- assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
-
- Attribute printOn = new Attribute(printCompilation.getName(), Boolean.TRUE);
-
- Object before = server.getAttribute(name, printCompilation.getName());
- server.setAttribute(name, printOn);
- Object after = server.getAttribute(name, printCompilation.getName());
-
- assertNull("Default value was not set", before);
- assertEquals("Changed to on", Boolean.TRUE, after);
- }
-
- private static Object findAttributeInfo(String attrName, Object info) {
- MBeanAttributeInfo printCompilation = null;
- for (MBeanAttributeInfo attr : ((MBeanInfo) info).getAttributes()) {
- if (attr.getName().equals(attrName)) {
- assertTrue("Readable", attr.isReadable());
- assertTrue("Writable", attr.isWritable());
- printCompilation = attr;
- break;
- }
- }
- return printCompilation;
- }
-
- @Test
- public void optionsAreCached() throws Exception {
- ObjectName name;
-
- assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
-
- HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
-
- OptionValues original = new OptionValues(EconomicMap.create());
-
- assertSame(original, realBean.optionsFor(original, null));
-
- assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
- final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
- ObjectInstance bean = server.getObjectInstance(name);
- assertNotNull("Bean is registered", bean);
- MBeanInfo info = server.getMBeanInfo(name);
- assertNotNull("Info is found", info);
-
- MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
-
- Attribute dumpTo1 = new Attribute(dump.getName(), 1);
-
- server.setAttribute(name, dumpTo1);
- Object after = server.getAttribute(name, dump.getName());
- assertEquals(1, after);
-
- final OptionValues modified1 = realBean.optionsFor(original, null);
- assertNotSame(original, modified1);
- final OptionValues modified2 = realBean.optionsFor(original, null);
- assertSame("Options are cached", modified1, modified2);
-
- }
-
- @Test
- public void dumpOperation() throws Exception {
- Field field = null;
- try {
- field = stopMBeanServer();
- } catch (Exception ex) {
- if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
- // skip on JDK9
- return;
- }
- }
- assertNull("The platformMBeanServer isn't initialized now", field.get(null));
-
- ObjectName name;
-
- assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
-
- HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
-
- assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
- final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
- ObjectInstance bean = server.getObjectInstance(name);
- assertNotNull("Bean is registered", bean);
-
- MBeanInfo info = server.getMBeanInfo(name);
- assertNotNull("Info is found", info);
-
- final MBeanOperationInfo[] arr = info.getOperations();
- assertEquals("Currently three overloads", 3, arr.length);
- MBeanOperationInfo dumpOp = null;
- for (int i = 0; i < arr.length; i++) {
- assertEquals("dumpMethod", arr[i].getName());
- if (arr[i].getSignature().length == 3) {
- dumpOp = arr[i];
- }
- }
- assertNotNull("three args variant found", dumpOp);
-
- server.invoke(name, "dumpMethod", new Object[]{
- "java.util.Arrays", "asList", ":3"
- }, null);
-
- MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
- Attribute dumpTo1 = new Attribute(dump.getName(), "");
- server.setAttribute(name, dumpTo1);
- Object after = server.getAttribute(name, dump.getName());
- assertEquals("", after);
-
- OptionValues empty = new OptionValues(EconomicMap.create());
- OptionValues unsetDump = realBean.optionsFor(empty, null);
- final MetaAccessProvider metaAccess = jdk.vm.ci.runtime.JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
- ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Arrays.class.getMethod("asList", Object[].class));
- final OptionValues forMethod = realBean.optionsFor(unsetDump, method);
- assertNotSame(unsetDump, forMethod);
- Object nothing = unsetDump.getMap().get(DebugOptions.Dump);
- assertEquals("Empty string", "", nothing);
-
- Object specialValue = forMethod.getMap().get(DebugOptions.Dump);
- assertEquals(":3", specialValue);
-
- OptionValues normalMethod = realBean.optionsFor(unsetDump, null);
- Object noSpecialValue = normalMethod.getMap().get(DebugOptions.Dump);
- assertEquals("Empty string", "", noSpecialValue);
- }
-
-}
--- /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/HotSpotGraalManagementTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.graalvm.compiler.hotspot.test.HotSpotGraalManagementTest.JunitShield.findAttributeInfo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import org.graalvm.compiler.api.test.Graal;
+import org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
+import org.graalvm.compiler.options.EnumOptionKey;
+import org.graalvm.compiler.options.NestedBooleanOptionKey;
+import org.graalvm.compiler.options.OptionDescriptor;
+import org.graalvm.compiler.options.OptionDescriptors;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionsParser;
+import org.junit.Assert;
+import org.junit.AssumptionViolatedException;
+import org.junit.Test;
+
+public class HotSpotGraalManagementTest {
+
+ private static final boolean DEBUG = Boolean.getBoolean(HotSpotGraalManagementTest.class.getSimpleName() + ".debug");
+
+ public HotSpotGraalManagementTest() {
+ try {
+ MBeanServerFactory.findMBeanServer(null);
+ } catch (NoClassDefFoundError e) {
+ throw new AssumptionViolatedException("Management classes/module(s) not available: " + e);
+ }
+ }
+
+ @Test
+ public void registration() throws Exception {
+ HotSpotGraalRuntime runtime = (HotSpotGraalRuntime) Graal.getRuntime();
+ HotSpotGraalManagementRegistration management = runtime.getManagement();
+ if (management == null) {
+ return;
+ }
+
+ MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ ObjectName name;
+ assertNotNull("Now the bean thinks it is registered", name = (ObjectName) management.poll(true));
+
+ assertNotNull("And the bean is found", server.getObjectInstance(name));
+ }
+
+ @Test
+ public void readBeanInfo() throws Exception {
+
+ assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
+
+ HotSpotGraalRuntime runtime = (HotSpotGraalRuntime) Graal.getRuntime();
+ HotSpotGraalManagementRegistration management = runtime.getManagement();
+ if (management == null) {
+ return;
+ }
+
+ ObjectName mbeanName;
+ assertNotNull("Bean is registered", mbeanName = (ObjectName) management.poll(true));
+ final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ ObjectInstance bean = server.getObjectInstance(mbeanName);
+ assertNotNull("Bean is registered", bean);
+ MBeanInfo info = server.getMBeanInfo(mbeanName);
+ assertNotNull("Info is found", info);
+
+ AttributeList originalValues = new AttributeList();
+ AttributeList newValues = new AttributeList();
+ for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
+ for (OptionDescriptor option : set) {
+ JunitShield.testOption(info, mbeanName, server, runtime, option, newValues, originalValues);
+ }
+ }
+
+ String[] attributeNames = new String[originalValues.size()];
+ for (int i = 0; i < attributeNames.length; i++) {
+ attributeNames[i] = ((Attribute) originalValues.get(i)).getName();
+ }
+ AttributeList actualValues = server.getAttributes(mbeanName, attributeNames);
+ assertEquals(originalValues.size(), actualValues.size());
+ for (int i = 0; i < attributeNames.length; i++) {
+ Object expect = String.valueOf(((Attribute) originalValues.get(i)).getValue());
+ Object actual = String.valueOf(((Attribute) actualValues.get(i)).getValue());
+ assertEquals(attributeNames[i], expect, actual);
+ }
+
+ try {
+ server.setAttributes(mbeanName, newValues);
+ } finally {
+ server.setAttributes(mbeanName, originalValues);
+ }
+ }
+
+ /**
+ * Junit scans all methods of a test class and tries to resolve all method parameter and return
+ * types. We hide such methods in an inner class to prevent errors such as:
+ *
+ * <pre>
+ * java.lang.NoClassDefFoundError: javax/management/MBeanInfo
+ * at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
+ * at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3119)
+ * at java.base/java.lang.Class.getDeclaredMethods(Class.java:2268)
+ * at org.junit.internal.MethodSorter.getDeclaredMethods(MethodSorter.java:54)
+ * at org.junit.runners.model.TestClass.scanAnnotatedMembers(TestClass.java:65)
+ * at org.junit.runners.model.TestClass.<init>(TestClass.java:57)
+ *
+ * </pre>
+ */
+ static class JunitShield {
+
+ /**
+ * Tests changing the value of {@code option} via the management interface to a) a new legal
+ * value and b) an illegal value.
+ */
+ static void testOption(MBeanInfo mbeanInfo,
+ ObjectName mbeanName,
+ MBeanServer server,
+ HotSpotGraalRuntime runtime,
+ OptionDescriptor option,
+ AttributeList newValues,
+ AttributeList originalValues) throws Exception {
+ OptionKey<?> optionKey = option.getOptionKey();
+ Object currentValue = optionKey.getValue(runtime.getOptions());
+ Class<?> optionType = option.getOptionValueType();
+ String name = option.getName();
+ if (DEBUG) {
+ System.out.println("Testing option " + name);
+ }
+ MBeanAttributeInfo attrInfo = findAttributeInfo(name, mbeanInfo);
+ assertNotNull("Attribute not found for option " + name, attrInfo);
+
+ String expectAttributeValue = stringValue(currentValue, option.getOptionValueType() == String.class);
+ Object actualAttributeValue = server.getAttribute(mbeanName, name);
+ assertEquals(expectAttributeValue, actualAttributeValue);
+
+ Map<String, String> legalValues = new HashMap<>();
+ List<String> illegalValues = new ArrayList<>();
+ if (optionKey instanceof EnumOptionKey) {
+ EnumOptionKey<?> enumOptionKey = (EnumOptionKey<?>) optionKey;
+ for (Object obj : enumOptionKey.getAllValues()) {
+ if (obj != currentValue) {
+ legalValues.put(obj.toString(), obj.toString());
+ }
+ }
+ illegalValues.add(String.valueOf(42));
+ } else if (optionType == Boolean.class) {
+ Object defaultValue;
+ if (optionKey instanceof NestedBooleanOptionKey) {
+ NestedBooleanOptionKey nbok = (NestedBooleanOptionKey) optionKey;
+ defaultValue = nbok.getMasterOption().getValue(runtime.getOptions());
+ } else {
+ defaultValue = optionKey.getDefaultValue();
+ }
+ legalValues.put("", unquotedStringValue(defaultValue));
+ illegalValues.add(String.valueOf(42));
+ illegalValues.add("true");
+ illegalValues.add("false");
+ } else if (optionType == String.class) {
+ legalValues.put("", quotedStringValue(optionKey.getDefaultValue()));
+ legalValues.put("\"" + currentValue + "Prime\"", "\"" + currentValue + "Prime\"");
+ legalValues.put("\"quoted string\"", "\"quoted string\"");
+ illegalValues.add("\"unbalanced quotes");
+ illegalValues.add("\"");
+ illegalValues.add("non quoted string");
+ } else if (optionType == Float.class) {
+ legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+ String value = unquotedStringValue(currentValue == null ? 33F : ((float) currentValue) + 11F);
+ legalValues.put(value, value);
+ illegalValues.add("string");
+ } else if (optionType == Double.class) {
+ legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+ String value = unquotedStringValue(currentValue == null ? 33D : ((double) currentValue) + 11D);
+ legalValues.put(value, value);
+ illegalValues.add("string");
+ } else if (optionType == Integer.class) {
+ legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+ String value = unquotedStringValue(currentValue == null ? 33 : ((int) currentValue) + 11);
+ legalValues.put(value, value);
+ illegalValues.add("42.42");
+ illegalValues.add("string");
+ } else if (optionType == Long.class) {
+ legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+ String value = unquotedStringValue(currentValue == null ? 33L : ((long) currentValue) + 11L);
+ legalValues.put(value, value);
+ illegalValues.add("42.42");
+ illegalValues.add("string");
+ }
+
+ Attribute originalAttributeValue = new Attribute(name, expectAttributeValue);
+ try {
+ for (Map.Entry<String, String> e : legalValues.entrySet()) {
+ String legalValue = e.getKey();
+ if (DEBUG) {
+ System.out.printf("Changing %s from %s to %s%n", name, currentValue, legalValue);
+ }
+ Attribute newAttributeValue = new Attribute(name, legalValue);
+ newValues.add(newAttributeValue);
+ server.setAttribute(mbeanName, newAttributeValue);
+ Object actual = optionKey.getValue(runtime.getOptions());
+ actual = server.getAttribute(mbeanName, name);
+ String expectValue = e.getValue();
+ if (option.getOptionValueType() == String.class && expectValue == null) {
+ expectValue = "";
+ } else if (option.getOptionKey() instanceof NestedBooleanOptionKey && null == expectValue) {
+ NestedBooleanOptionKey nbok = (NestedBooleanOptionKey) option.getOptionKey();
+ expectValue = String.valueOf(nbok.getValue(runtime.getOptions()));
+ actual = server.getAttribute(mbeanName, name);
+ }
+ assertEquals(expectValue, actual);
+ }
+ } finally {
+ if (DEBUG) {
+ System.out.printf("Resetting %s to %s%n", name, currentValue);
+ }
+ originalValues.add(originalAttributeValue);
+ server.setAttribute(mbeanName, originalAttributeValue);
+ }
+
+ try {
+ for (Object illegalValue : illegalValues) {
+ if (DEBUG) {
+ System.out.printf("Changing %s from %s to illegal value %s%n", name, currentValue, illegalValue);
+ }
+ server.setAttribute(mbeanName, new Attribute(name, illegalValue));
+ Assert.fail("Expected setting " + name + " to " + illegalValue + " to fail");
+ }
+ } catch (InvalidAttributeValueException e) {
+ // Expected
+ } finally {
+ if (DEBUG) {
+ System.out.printf("Resetting %s to %s%n", name, currentValue);
+ }
+ server.setAttribute(mbeanName, originalAttributeValue);
+ }
+
+ try {
+
+ String unknownOptionName = "definitely not an option name";
+ server.setAttribute(mbeanName, new Attribute(unknownOptionName, ""));
+ Assert.fail("Expected setting option with name \"" + unknownOptionName + "\" to fail");
+ } catch (AttributeNotFoundException e) {
+ // Expected
+ }
+ }
+
+ static MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) {
+ for (MBeanAttributeInfo attr : info.getAttributes()) {
+ if (attr.getName().equals(attrName)) {
+ assertTrue("Readable", attr.isReadable());
+ assertTrue("Writable", attr.isWritable());
+ return attr;
+ }
+ }
+ return null;
+ }
+ }
+
+ private static String quotedStringValue(Object optionValue) {
+ return stringValue(optionValue, true);
+ }
+
+ private static String unquotedStringValue(Object optionValue) {
+ return stringValue(optionValue, false);
+ }
+
+ private static String stringValue(Object optionValue, boolean withQuoting) {
+ if (optionValue == null) {
+ return "";
+ }
+ if (withQuoting) {
+ return "\"" + optionValue + "\"";
+ }
+ return String.valueOf(optionValue);
+ }
+
+ private static String quoted(Object s) {
+ return "\"" + s + "\"";
+ }
+
+ /**
+ * Tests publicaly visible names and identifiers used by tools developed and distributed on an
+ * independent schedule (like VisualVM). Consider keeping the test passing without any semantic
+ * modifications. The cost of changes is higher than you estimate. Include all available
+ * stakeholders as reviewers to give them a chance to stop you before causing too much damage.
+ */
+ @Test
+ public void publicJmxApiOfGraalDumpOperation() throws Exception {
+ assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
+
+ HotSpotGraalRuntime runtime = (HotSpotGraalRuntime) Graal.getRuntime();
+ HotSpotGraalManagementRegistration management = runtime.getManagement();
+ if (management == null) {
+ return;
+ }
+
+ ObjectName mbeanName;
+ assertNotNull("Bean is registered", mbeanName = (ObjectName) management.poll(true));
+ final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ assertEquals("Domain name is used to lookup the beans by VisualVM", "org.graalvm.compiler.hotspot", mbeanName.getDomain());
+ assertEquals("type can be used to identify the Graal bean", "HotSpotGraalRuntime_VM", mbeanName.getKeyProperty("type"));
+
+ ObjectInstance bean = server.getObjectInstance(mbeanName);
+ assertNotNull("Bean is registered", bean);
+
+ MBeanInfo info = server.getMBeanInfo(mbeanName);
+ assertNotNull("Info is found", info);
+
+ final MBeanOperationInfo[] arr = info.getOperations();
+ assertEquals("Currently three overloads", 3, arr.length);
+ MBeanOperationInfo dumpOp = null;
+ for (int i = 0; i < arr.length; i++) {
+ assertEquals("dumpMethod", arr[i].getName());
+ if (arr[i].getSignature().length == 3) {
+ dumpOp = arr[i];
+ }
+ }
+ assertNotNull("three args variant (as used by VisualVM) found", dumpOp);
+
+ MBeanAttributeInfo dumpPath = findAttributeInfo("DumpPath", info);
+ MBeanAttributeInfo printGraphFile = findAttributeInfo("PrintGraphFile", info);
+ MBeanAttributeInfo showDumpFiles = findAttributeInfo("ShowDumpFiles", info);
+ Object originalDumpPath = server.getAttribute(mbeanName, dumpPath.getName());
+ Object originalPrintGraphFile = server.getAttribute(mbeanName, printGraphFile.getName());
+ Object originalShowDumpFiles = server.getAttribute(mbeanName, showDumpFiles.getName());
+ final File tmpDir = new File(HotSpotGraalManagementTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
+
+ server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), quoted(tmpDir)));
+ // Force output to a file even if there's a running IGV instance available.
+ server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), true));
+ server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), false));
+ Object[] params = {"java.util.Arrays", "asList", ":3"};
+ try {
+ server.invoke(mbeanName, "dumpMethod", params, null);
+ boolean found = false;
+ String expectedIgvDumpSuffix = "[Arrays.asList(Object[])List].bgv";
+ List<String> dumpPathEntries = Arrays.asList(tmpDir.list());
+ for (String entry : dumpPathEntries) {
+ if (entry.endsWith(expectedIgvDumpSuffix)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ Assert.fail(String.format("Expected file ending with \"%s\" in %s but only found:%n%s", expectedIgvDumpSuffix, tmpDir,
+ dumpPathEntries.stream().collect(Collectors.joining(System.lineSeparator()))));
+ }
+ } finally {
+ deleteDirectory(tmpDir.toPath());
+ server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), originalDumpPath));
+ server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), originalPrintGraphFile));
+ server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), originalShowDumpFiles));
+ }
+ }
+
+ static void deleteDirectory(Path toDelete) throws IOException {
+ Files.walk(toDelete).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -46,6 +46,17 @@
test("getClass0", "a string");
test("objectHashCode", obj);
+
+ testGraph("objectNotify", "Object.notify");
+ testGraph("objectNotifyAll", "Object.notifyAll");
+
+ synchronized (obj) {
+ test("objectNotify", obj);
+ test("objectNotifyAll", obj);
+ }
+ // Test with IllegalMonitorStateException (no synchronized block)
+ test("objectNotify", obj);
+ test("objectNotifyAll", obj);
}
@SuppressWarnings("all")
@@ -58,6 +69,16 @@
return obj.hashCode();
}
+ @SuppressWarnings("all")
+ public static void objectNotify(Object obj) {
+ obj.notify();
+ }
+
+ @SuppressWarnings("all")
+ public static void objectNotifyAll(Object obj) {
+ obj.notifyAll();
+ }
+
@Test
public void testClassSubstitutions() {
testGraph("getModifiers");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,6 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp;
import org.junit.Assume;
-import org.junit.Ignore;
import org.junit.Test;
import jdk.vm.ci.meta.JavaConstant;
@@ -37,7 +36,6 @@
public class HotSpotStampMemoryAccessTest extends HotSpotGraalCompilerTest {
- @Ignore("not all versions are safe yet")
@Test
public void testReadNarrowObject() {
CompressEncoding oopEncoding = runtime().getVMConfig().getOopEncoding();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.api.test.Graal;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+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;
@@ -59,7 +59,7 @@
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import org.junit.Assert;
import org.junit.Test;
--- /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/aaa Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.test;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
+import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
+import org.graalvm.compiler.java.GraphBuilderPhase;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class HotSpotLazyInitializationTest extends GraalCompilerTest {
+
+ HotSpotClassInitializationPlugin classInitPlugin = new HotSpotClassInitializationPlugin();
+
+ @Override
+ protected Plugins getDefaultGraphBuilderPlugins() {
+ Plugins plugins = super.getDefaultGraphBuilderPlugins();
+ plugins.setClassInitializationPlugin(classInitPlugin);
+ return plugins;
+ }
+
+ static boolean X_initialized = false;
+
+ static class X {
+ static {
+ X_initialized = true;
+ }
+ static void foo() {}
+ }
+
+ public static void invokeStatic() {
+ X.foo();
+ }
+
+ private void test(String name) {
+ ResolvedJavaMethod method = getResolvedJavaMethod(name);
+ Assume.assumeTrue("skipping for old JVMCI", classInitPlugin.supportsLazyInitialization(method.getConstantPool()));
+ StructuredGraph graph = parseEager(method, AllowAssumptions.NO);
+ Assert.assertFalse(X_initialized);
+ }
+
+ @Test
+ public void test1() {
+ test("invokeStatic");
+ }
+
+}
--- /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/CommunityCompilerConfigurationFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot;
+
+import org.graalvm.compiler.core.phases.CommunityCompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.serviceprovider.ServiceProvider;
+
+/**
+ * Factory for creating the default configuration for the community edition of Graal.
+ */
+@ServiceProvider(CompilerConfigurationFactory.class)
+public class CommunityCompilerConfigurationFactory extends CompilerConfigurationFactory {
+
+ public static final String NAME = "community";
+
+ /**
+ * Must be greater than {@link EconomyCompilerConfigurationFactory#AUTO_SELECTION_PRIORITY}.
+ */
+ public static final int AUTO_SELECTION_PRIORITY = 2;
+
+ public CommunityCompilerConfigurationFactory() {
+ super(NAME, AUTO_SELECTION_PRIORITY);
+ assert AUTO_SELECTION_PRIORITY > EconomyCompilerConfigurationFactory.AUTO_SELECTION_PRIORITY;
+ }
+
+ @Override
+ public CompilerConfiguration createCompilerConfiguration() {
+ return new CommunityCompilerConfiguration();
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,10 +42,10 @@
import java.util.concurrent.ConcurrentLinkedDeque;
import org.graalvm.compiler.debug.CSVUtil;
-import org.graalvm.compiler.debug.Management;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.hotspot.HotSpotInstalledCode;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -87,8 +87,7 @@
private static long zeroTime = System.nanoTime();
private static long getThreadAllocatedBytes() {
- com.sun.management.ThreadMXBean thread = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
- return thread.getThreadAllocatedBytes(currentThread().getId());
+ return GraalServices.getCurrentThreadAllocatedBytes();
}
@NotReported private final long startTime;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,14 +22,16 @@
*/
package org.graalvm.compiler.hotspot;
+import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.CompilationPrinter;
@@ -140,17 +142,25 @@
}
@Override
- protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey) {
- /*
- * Automatically exit VM on non-bailout during bootstrap or when asserts are enabled but
- * respect CompilationFailureAction if it has been explicitly set.
- */
- if (actionKey == CompilationFailureAction && !actionKey.hasBeenSet(values)) {
- if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
- return ExitVM;
+ protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
+ // Respect current action if it has been explicitly set.
+ if (!actionKey.hasBeenSet(values)) {
+ if (actionKey == CompilationFailureAction) {
+ // Automatically exit on non-bailout during bootstrap
+ // or when assertions are enabled.
+ if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+ return ExitVM;
+ }
+ } else if (actionKey == CompilationBailoutAction && ((BailoutException) cause).isPermanent()) {
+ // Get more info for permanent bailouts during bootstrap
+ // or when assertions are enabled.
+ assert CompilationBailoutAction.getDefaultValue() == ExceptionAction.Silent;
+ if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+ return Diagnose;
+ }
}
}
- return super.lookupAction(values, actionKey);
+ return super.lookupAction(values, actionKey, cause);
}
@SuppressWarnings("try")
@@ -187,6 +197,7 @@
}
return null;
}
+
}
public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
import java.util.List;
import java.util.stream.Collectors;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.lir.phases.LIRPhase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CoreCompilerConfigurationFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.hotspot;
-
-import org.graalvm.compiler.core.phases.CoreCompilerConfiguration;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.serviceprovider.ServiceProvider;
-
-@ServiceProvider(CompilerConfigurationFactory.class)
-public class CoreCompilerConfigurationFactory extends CompilerConfigurationFactory {
-
- public static final String NAME = "core";
-
- public static final int AUTO_SELECTION_PRIORITY = 2;
-
- public CoreCompilerConfigurationFactory() {
- super(NAME, AUTO_SELECTION_PRIORITY);
- }
-
- @Override
- public CompilerConfiguration createCompilerConfiguration() {
- return new CoreCompilerConfiguration();
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,9 @@
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
+/**
+ * Factory that creates a {@link EconomyCompilerConfiguration}.
+ */
@ServiceProvider(CompilerConfigurationFactory.class)
public class EconomyCompilerConfigurationFactory extends CompilerConfigurationFactory {
@@ -44,7 +47,7 @@
@Override
public BackendMap createBackendMap() {
- // the economy configuration only differs in the frontend, it reuses the "core" backend
- return new DefaultBackendMap(CoreCompilerConfigurationFactory.NAME);
+ // the economy configuration only differs in the frontend, it reuses the "community" backend
+ return new DefaultBackendMap(CommunityCompilerConfigurationFactory.NAME);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,33 +25,16 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import org.graalvm.compiler.api.replacements.Fold;
-import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
/**
* Used to access native configuration details.
*/
-public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
-
- /**
- * Sentinel value to use for an {@linkplain InjectedParameter injected}
- * {@link GraalHotSpotVMConfig} parameter to a {@linkplain Fold foldable} method.
- */
- public static final GraalHotSpotVMConfig INJECTED_VMCONFIG = null;
-
- // this uses `1.9` which will give the correct result with `1.9`, `9`, `10` etc.
- private final boolean isJDK8 = System.getProperty("java.specification.version").compareTo("1.9") < 0;
- private final int jdkVersion = isJDK8 ? 8 : Integer.parseInt(System.getProperty("java.specification.version"));
- public final String osName = getHostOSName();
- public final String osArch = getHostArchitectureName();
- public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
- public final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
GraalHotSpotVMConfig(HotSpotVMConfigStore store) {
super(store);
@@ -64,29 +47,6 @@
assert check();
}
- /**
- * Gets the value of a static C++ field under two possible names. {@code name} is the preferred
- * name and will be checked first.
- *
- * @param name fully qualified name of the field
- * @param alternateName fully qualified alternate name of the field
- * @param type the boxed type to which the constant value will be converted
- * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
- * @return the value of the requested field
- * @throws JVMCIError if the field is not static or not present
- */
- public <T> T getFieldValueWithAlternate(String name, String alternateName, Class<T> type, String cppType) {
- try {
- return getFieldValue(name, type, cppType);
- } catch (JVMCIError e) {
- try {
- return getFieldValue(alternateName, type, cppType);
- } catch (JVMCIError e2) {
- throw new JVMCIError("expected VM field not found: " + name + " or " + alternateName);
- }
- }
- }
-
private final CompressEncoding oopEncoding;
private final CompressEncoding klassEncoding;
@@ -98,50 +58,6 @@
return klassEncoding;
}
- /**
- * Gets the host operating system name.
- */
- private static String getHostOSName() {
- String osName = System.getProperty("os.name");
- switch (osName) {
- case "Linux":
- osName = "linux";
- break;
- case "SunOS":
- osName = "solaris";
- break;
- case "Mac OS X":
- osName = "bsd";
- break;
- default:
- // Of course Windows is different...
- if (osName.startsWith("Windows")) {
- osName = "windows";
- } else {
- throw new JVMCIError("Unexpected OS name: " + osName);
- }
- }
- return osName;
- }
-
- private static String getHostArchitectureName() {
- String arch = System.getProperty("os.arch");
- switch (arch) {
- case "x86_64":
- arch = "amd64";
- break;
- case "sparcv9":
- arch = "sparc";
- break;
- }
- return arch;
- }
-
- private final Integer intRequiredOnAMD64 = osArch.equals("amd64") ? null : 0;
- private final Long longRequiredOnAMD64 = osArch.equals("amd64") ? null : 0L;
- private final Integer intNotPresentInJDK8 = isJDK8 ? 0 : null;
- private final Long longNotPresentInJDK8 = isJDK8 ? 0L : null;
-
public final boolean cAssertions = getConstant("ASSERT", Boolean.class);
public final int codeEntryAlignment = getFlag("CodeEntryAlignment", Integer.class);
@@ -157,6 +73,7 @@
public final int hugeMethodLimit = getFlag("HugeMethodLimit", Integer.class);
public final boolean printInlining = getFlag("PrintInlining", Boolean.class);
public final boolean inline = getFlag("Inline", Boolean.class);
+ public final boolean inlineNotify = versioned.inlineNotify;
public final boolean useFastLocking = getFlag("JVMCIUseFastLocking", Boolean.class);
public final boolean forceUnreachable = getFlag("ForceUnreachable", Boolean.class);
public final int codeSegmentSize = getFlag("CodeCacheSegmentSize", Integer.class);
@@ -168,7 +85,7 @@
public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class);
public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class);
public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class);
- public final boolean useCRC32CIntrinsics = isJDK8 ? false : getFlag("UseCRC32CIntrinsics", Boolean.class);
+ public final boolean useCRC32CIntrinsics = versioned.useCRC32CIntrinsics;
public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false);
private final boolean useMultiplyToLenIntrinsic = getFlag("UseMultiplyToLenIntrinsic", Boolean.class);
@@ -216,6 +133,14 @@
return useSquareToLenIntrinsic && squareToLen != 0;
}
+ public boolean inlineNotify() {
+ return inlineNotify && notifyAddress != 0;
+ }
+
+ public boolean inlineNotifyAll() {
+ return inlineNotify && notifyAllAddress != 0;
+ }
+
public final boolean useG1GC = getFlag("UseG1GC", Boolean.class);
public final boolean useCMSGC = getFlag("UseConcMarkSweepGC", Boolean.class);
@@ -383,7 +308,7 @@
public final int threadIsMethodHandleReturnOffset = getFieldOffset("JavaThread::_is_method_handle_return", Integer.class, "int");
public final int threadObjectResultOffset = getFieldOffset("JavaThread::_vm_result", Integer.class, "oop");
public final int jvmciCountersThreadOffset = getFieldOffset("JavaThread::_jvmci_counters", Integer.class, "jlong*");
- public final int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address", intNotPresentInJDK8);
+ public final int javaThreadReservedStackActivationOffset = versioned.javaThreadReservedStackActivationOffset;
/**
* An invalid value for {@link #rtldDefault}.
@@ -504,14 +429,14 @@
public final int methodAccessFlagsOffset = getFieldOffset("Method::_access_flags", Integer.class, "AccessFlags");
public final int methodConstMethodOffset = getFieldOffset("Method::_constMethod", Integer.class, "ConstMethod*");
- public final int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, isJDK8 ? "u1" : "u2");
- public final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, isJDK8 ? "u1" : "u2");
+ public final int methodIntrinsicIdOffset = versioned.methodIntrinsicIdOffset;
+ public final int methodFlagsOffset = versioned.methodFlagsOffset;
public final int methodVtableIndexOffset = getFieldOffset("Method::_vtable_index", Integer.class, "int");
public final int methodCountersOffset = getFieldOffset("Method::_method_counters", Integer.class, "MethodCounters*");
public final int methodDataOffset = getFieldOffset("Method::_method_data", Integer.class, "MethodData*");
public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address");
- public final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, isJDK8 ? "nmethod*" : "CompiledMethod*");
+ public final int methodCodeOffset = versioned.methodCodeOffset;
public final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
public final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
@@ -522,8 +447,8 @@
public final int invocationCounterOffset = getFieldOffset("MethodCounters::_invocation_counter", Integer.class, "InvocationCounter");
public final int backedgeCounterOffset = getFieldOffset("MethodCounters::_backedge_counter", Integer.class, "InvocationCounter");
- public final int invocationCounterIncrement = getConstant("InvocationCounter::count_increment", Integer.class, intNotPresentInJDK8);
- public final int invocationCounterShift = getConstant("InvocationCounter::count_shift", Integer.class, intNotPresentInJDK8);
+ public final int invocationCounterIncrement = versioned.invocationCounterIncrement;
+ public final int invocationCounterShift = versioned.invocationCounterShift;
public final int nmethodEntryOffset = getFieldOffset("nmethod::_verified_entry_point",
Integer.class, "address");
@@ -548,11 +473,6 @@
public final int logOfHRGrainBytes = getFieldValue("HeapRegion::LogOfHRGrainBytes", Integer.class, "int");
- public final byte dirtyCardValue = jdkVersion >= 11 ? getConstant("CardTable::dirty_card", Byte.class)
- : (jdkVersion > 8 ? getConstant("CardTableModRefBS::dirty_card", Byte.class) : getFieldValue("CompilerToVM::Data::dirty_card", Byte.class, "int"));
- public final byte g1YoungCardValue = jdkVersion >= 11 ? getConstant("G1CardTable::g1_young_gen", Byte.class)
- : (jdkVersion > 8 ? getConstant("G1SATBCardTableModRefBS::g1_young_gen", Byte.class) : getFieldValue("CompilerToVM::Data::g1_young_card", Byte.class, "int"));
-
public final long cardtableStartAddress = getFieldValue("CompilerToVM::Data::cardtable_start_address", Long.class, "jbyte*");
public final int cardtableShift = getFieldValue("CompilerToVM::Data::cardtable_shift", Integer.class, "int");
@@ -560,17 +480,20 @@
* This is the largest stack offset encodeable in an OopMapValue. Offsets larger than this will
* throw an exception during code installation.
*/
- public final int maxOopMapStackOffset = getFieldValueWithAlternate("CompilerToVM::Data::_max_oop_map_stack_offset", "JVMCIRuntime::max_oop_map_stack_offset", Integer.class, "int");
+ public final int maxOopMapStackOffset = getFieldValue("CompilerToVM::Data::_max_oop_map_stack_offset", Integer.class, "int");
public final long safepointPollingAddress = getFieldValue("os::_polling_page", Long.class, "address");
// G1 Collector Related Values.
- public final int g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class);
- public final int g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class);
- public final int g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class);
- public final int g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class);
- public final int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class);
+ public final byte dirtyCardValue = versioned.dirtyCardValue;
+ public final byte g1YoungCardValue = versioned.g1YoungCardValue;
+
+ public final int g1SATBQueueMarkingOffset = versioned.g1SATBQueueMarkingOffset;
+ public final int g1SATBQueueIndexOffset = versioned.g1SATBQueueIndexOffset;
+ public final int g1SATBQueueBufferOffset = versioned.g1SATBQueueBufferOffset;
+ public final int g1CardQueueIndexOffset = versioned.g1CardQueueIndexOffset;
+ public final int g1CardQueueBufferOffset = versioned.g1CardQueueBufferOffset;
public final int klassOffset = getFieldValue("java_lang_Class::_klass_offset", Integer.class, "int");
public final int arrayKlassOffset = getFieldValue("java_lang_Class::_array_klass_offset", Integer.class, "int");
@@ -636,7 +559,7 @@
// FIXME This is only temporary until the GC code is changed.
public final boolean inlineContiguousAllocationSupported = getFieldValue("CompilerToVM::Data::_supports_inline_contig_alloc", Boolean.class);
public final long heapEndAddress = getFieldValue("CompilerToVM::Data::_heap_end_addr", Long.class, "HeapWord**");
- public final long heapTopAddress = getFieldValue("CompilerToVM::Data::_heap_top_addr", Long.class, isJDK8 ? "HeapWord**" : "HeapWord* volatile*");
+ public final long heapTopAddress = versioned.heapTopAddress;
public final boolean cmsIncrementalMode = getFlag("CMSIncrementalMode", Boolean.class, false);
@@ -646,8 +569,8 @@
public final long handleDeoptStub = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", Long.class, "address");
public final long uncommonTrapStub = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", Long.class, "address");
- public final long codeCacheLowBound = getFieldValue(isJDK8 ? "CompilerToVM::Data::CodeCache_low_bound" : "CodeCache::_low_bound", Long.class, "address");
- public final long codeCacheHighBound = getFieldValue(isJDK8 ? "CompilerToVM::Data::CodeCache_high_bound" : "CodeCache::_high_bound", Long.class, "address");
+ public final long codeCacheLowBound = versioned.codeCacheLowBound;
+ public final long codeCacheHighBound = versioned.codeCacheHighBound;
public final long aescryptEncryptBlockStub = getFieldValue("StubRoutines::_aescrypt_encryptBlock", Long.class, "address");
public final long aescryptDecryptBlockStub = getFieldValue("StubRoutines::_aescrypt_decryptBlock", Long.class, "address");
@@ -675,7 +598,7 @@
public final long montgomerySquare = getFieldValue("StubRoutines::_montgomerySquare", Long.class, "address", longRequiredOnAMD64);
public final long vectorizedMismatch = getFieldValue("StubRoutines::_vectorizedMismatch", Long.class, "address", 0L);
- public final long throwDelayedStackOverflowErrorEntry = getFieldValue("StubRoutines::_throw_delayed_StackOverflowError_entry", Long.class, "address", longNotPresentInJDK8);
+ public final long throwDelayedStackOverflowErrorEntry = versioned.throwDelayedStackOverflowErrorEntry;
public final long jbyteArraycopy = getFieldValue("StubRoutines::_jbyte_arraycopy", Long.class, "address");
public final long jshortArraycopy = getFieldValue("StubRoutines::_jshort_arraycopy", Long.class, "address");
@@ -718,6 +641,8 @@
public final long exceptionHandlerForPcAddress = getAddress("JVMCIRuntime::exception_handler_for_pc");
public final long monitorenterAddress = getAddress("JVMCIRuntime::monitorenter");
public final long monitorexitAddress = getAddress("JVMCIRuntime::monitorexit");
+ public final long notifyAddress = getAddress("JVMCIRuntime::object_notify", 0L);
+ public final long notifyAllAddress = getAddress("JVMCIRuntime::object_notifyAll", 0L);
public final long throwAndPostJvmtiExceptionAddress = getAddress("JVMCIRuntime::throw_and_post_jvmti_exception");
public final long throwKlassExternalNameExceptionAddress = getAddress("JVMCIRuntime::throw_klass_external_name_exception");
public final long throwClassCastExceptionAddress = getAddress("JVMCIRuntime::throw_class_cast_exception");
@@ -735,7 +660,7 @@
public final long registerFinalizerAddress = getAddress("SharedRuntime::register_finalizer");
public final long exceptionHandlerForReturnAddressAddress = getAddress("SharedRuntime::exception_handler_for_return_address");
public final long osrMigrationEndAddress = getAddress("SharedRuntime::OSR_migration_end");
- public final long enableStackReservedZoneAddress = getAddress("SharedRuntime::enable_stack_reserved_zone", longNotPresentInJDK8);
+ public final long enableStackReservedZoneAddress = versioned.enableStackReservedZoneAddress;
public final long javaTimeMillisAddress = getAddress("os::javaTimeMillis");
public final long javaTimeNanosAddress = getAddress("os::javaTimeNanos");
--- /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/GraalHotSpotVMConfigBase.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 org.graalvm.compiler.api.replacements.Fold;
+import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * This is a source with different versions for various JDKs.
+ */
+public abstract class GraalHotSpotVMConfigBase extends HotSpotVMConfigAccess {
+
+ GraalHotSpotVMConfigBase(HotSpotVMConfigStore store) {
+ super(store);
+ assert this instanceof GraalHotSpotVMConfig;
+ versioned = new GraalHotSpotVMConfigVersioned(store);
+ }
+
+ /**
+ * Contains values that are different between JDK versions.
+ */
+ protected final GraalHotSpotVMConfigVersioned versioned;
+
+ /**
+ * Sentinel value to use for an {@linkplain InjectedParameter injected}
+ * {@link GraalHotSpotVMConfig} parameter to a {@linkplain Fold foldable} method.
+ */
+ public static final GraalHotSpotVMConfig INJECTED_VMCONFIG = null;
+
+ public final String osName = getHostOSName();
+ public final String osArch = getHostArchitectureName();
+ public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+ public final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+
+ /**
+ * Gets the host operating system name.
+ */
+ private static String getHostOSName() {
+ String osName = System.getProperty("os.name");
+ switch (osName) {
+ case "Linux":
+ osName = "linux";
+ break;
+ case "SunOS":
+ osName = "solaris";
+ break;
+ case "Mac OS X":
+ osName = "bsd";
+ break;
+ default:
+ // Of course Windows is different...
+ if (osName.startsWith("Windows")) {
+ osName = "windows";
+ } else {
+ throw new JVMCIError("Unexpected OS name: " + osName);
+ }
+ }
+ return osName;
+ }
+
+ private static String getHostArchitectureName() {
+ String arch = System.getProperty("os.arch");
+ switch (arch) {
+ case "x86_64":
+ arch = "amd64";
+ break;
+ case "sparcv9":
+ arch = "sparc";
+ break;
+ }
+ return arch;
+ }
+
+ protected final Integer intRequiredOnAMD64 = osArch.equals("amd64") ? null : 0;
+ protected final Long longRequiredOnAMD64 = osArch.equals("amd64") ? null : 0L;
+}
--- /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/GraalHotSpotVMConfigVersioned.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * This is a source with different versions for various JDKs. When modifying/adding a field in this
+ * class accessed from outside this class, be sure to update the field appropriately in all source
+ * files named {@code GraalHotSpotVMConfigVersioned.java}.
+ *
+ * Fields are grouped according to the most recent JBS issue showing why they are versioned.
+ *
+ * JDK Version: 11+
+ */
+final class GraalHotSpotVMConfigVersioned extends HotSpotVMConfigAccess {
+
+ GraalHotSpotVMConfigVersioned(HotSpotVMConfigStore store) {
+ super(store);
+ }
+
+ // JDK-8073583
+ final boolean useCRC32CIntrinsics = getFlag("UseCRC32CIntrinsics", Boolean.class);
+
+ // JDK-8075171
+ final boolean inlineNotify = getFlag("InlineNotify", Boolean.class);
+
+ // JDK-8046936
+ final int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address");
+ final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, "u2");
+ final long throwDelayedStackOverflowErrorEntry = getFieldValue("StubRoutines::_throw_delayed_StackOverflowError_entry", Long.class, "address");
+ final long enableStackReservedZoneAddress = getAddress("SharedRuntime::enable_stack_reserved_zone");
+
+ // JDK-8135085
+ final int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, "u2");
+
+ // JDK-8151956
+ final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, "CompiledMethod*");
+
+ // JDK-8059606
+ final int invocationCounterIncrement = getConstant("InvocationCounter::count_increment", Integer.class);
+ final int invocationCounterShift = getConstant("InvocationCounter::count_shift", Integer.class);
+
+ // JDK-8195142
+ final byte dirtyCardValue = getConstant("CardTable::dirty_card", Byte.class);
+ final byte g1YoungCardValue = getConstant("G1CardTable::g1_young_gen", Byte.class);
+
+ // JDK-8201318
+ final int g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class);
+ final int g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class);
+ final int g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class);
+ final int g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class);
+ final int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class);
+
+ // JDK-8033552
+ final long heapTopAddress = getFieldValue("CompilerToVM::Data::_heap_top_addr", Long.class, "HeapWord* volatile*");
+
+ // JDK-8015774
+ final long codeCacheLowBound = getFieldValue("CodeCache::_low_bound", Long.class, "address");
+ final long codeCacheHighBound = getFieldValue("CodeCache::_high_bound", Long.class, "address");
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Thu Apr 26 17:59:02 2018 +0200
@@ -64,11 +64,11 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.tiers.SuitesProvider;
import org.graalvm.compiler.word.Word;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.word.Pointer;
import jdk.vm.ci.code.CompilationRequest;
import jdk.vm.ci.code.CompiledCode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -221,6 +221,10 @@
List<Site> sourcePositionSites = new ArrayList<>();
for (SourceMapping source : target.getSourceMappings()) {
NodeSourcePosition sourcePosition = source.getSourcePosition();
+ if (sourcePosition.isPlaceholder() || sourcePosition.isSubstitution()) {
+ // HotSpot doesn't understand any of the special positions so just drop them.
+ continue;
+ }
assert sourcePosition.verify();
sourcePosition = sourcePosition.trim();
/*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
import java.util.Arrays;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.debug.GraalError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.hotspot.stubs.Stub;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* The details required to link a HotSpot runtime or stub call.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,13 +25,13 @@
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CallingConvention.Type;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,9 +38,9 @@
import org.graalvm.compiler.core.GraalCompiler;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.util.CompilationAlarm;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugContext.Activation;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.hotspot.CompilationCounters.Options;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
@@ -105,17 +105,16 @@
@Override
public CompilationRequestResult compileMethod(CompilationRequest request) {
- return compileMethod(request, true);
+ return compileMethod(request, true, graalRuntime.getOptions());
}
@SuppressWarnings("try")
- CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault) {
+ CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues options) {
if (graalRuntime.isShutdown()) {
return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false);
}
ResolvedJavaMethod method = request.getMethod();
- OptionValues options = graalRuntime.getOptions(method);
if (graalRuntime.isBootstrapping()) {
if (DebugOptions.BootstrapInitializeOnly.getValue(options)) {
@@ -282,13 +281,6 @@
return suite;
}
- public Object mbean() {
- if (graalRuntime instanceof HotSpotGraalRuntime) {
- return ((HotSpotGraalRuntime) graalRuntime).getMBean();
- }
- return null;
- }
-
/**
* Converts {@code method} to a String with {@link JavaMethod#format(String)} and the format
* string {@code "%H.%n(%p)"}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,9 +26,8 @@
import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX;
import java.io.PrintStream;
-import java.util.Collections;
-import java.util.Map;
+import org.graalvm.compiler.api.runtime.GraalRuntime;
import org.graalvm.compiler.debug.MethodFilter;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
@@ -36,7 +35,6 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.options.OptionsParser;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
import jdk.vm.ci.common.InitTimer;
import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
@@ -49,21 +47,7 @@
private static MethodFilter[] graalCompileOnlyFilter;
private static boolean compileGraalWithC1Only;
- /**
- * Module containing {@link HotSpotJVMCICompilerFactory}.
- */
- private Object jvmciModule;
-
- /**
- * Module containing {@link HotSpotGraalCompilerFactory}.
- */
- private Object graalModule;
-
- /**
- * Module containing the {@linkplain CompilerConfigurationFactory#selectFactory selected}
- * configuration.
- */
- private Object compilerConfigurationModule;
+ private IsGraalPredicate isGraalPredicate;
private final HotSpotGraalJVMCIServiceLocator locator;
@@ -87,10 +71,7 @@
assert options == null : "cannot select " + getClass() + " service more than once";
options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
initializeGraalCompilePolicyFields(options);
- if (!JDK9Method.Java8OrEarlier) {
- jvmciModule = JDK9Method.getModule(HotSpotJVMCICompilerFactory.class);
- graalModule = JDK9Method.getModule(HotSpotGraalCompilerFactory.class);
- }
+ isGraalPredicate = compileGraalWithC1Only ? new IsGraalPredicate() : null;
/*
* Exercise this code path early to encourage loading now. This doesn't solve problem of
* deadlock during class loading but seems to eliminate it in practice.
@@ -134,10 +115,10 @@
@Override
public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) {
CompilerConfigurationFactory factory = CompilerConfigurationFactory.selectFactory(null, options);
- if (!JDK9Method.Java8OrEarlier) {
- compilerConfigurationModule = JDK9Method.getModule(factory.getClass());
+ if (isGraalPredicate != null) {
+ isGraalPredicate.onCompilerConfigurationFactorySelection(factory);
}
- HotSpotGraalCompiler compiler = createCompiler(runtime, options, factory);
+ HotSpotGraalCompiler compiler = createCompiler("VM", runtime, options, factory);
// Only the HotSpotGraalRuntime associated with the compiler created via
// jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving
// VM events.
@@ -149,14 +130,17 @@
* Creates a new {@link HotSpotGraalRuntime} object and a new {@link HotSpotGraalCompiler} and
* returns the latter.
*
+ * @param runtimeNameQualifier a qualifier to be added to the {@linkplain GraalRuntime#getName()
+ * name} of the {@linkplain HotSpotGraalCompiler#getGraalRuntime() runtime} created
+ * by this method
* @param runtime the JVMCI runtime on which the {@link HotSpotGraalRuntime} is built
* @param compilerConfigurationFactory factory for the {@link CompilerConfiguration}
*/
@SuppressWarnings("try")
- public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) {
+ public static HotSpotGraalCompiler createCompiler(String runtimeNameQualifier, JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) {
HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime;
try (InitTimer t = timer("HotSpotGraalRuntime.<init>")) {
- HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options);
+ HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(runtimeNameQualifier, jvmciRuntime, compilerConfigurationFactory, options);
return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime, graalRuntime.getOptions());
}
}
@@ -187,54 +171,11 @@
assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory");
}
- static final ClassLoader JVMCI_LOADER = HotSpotGraalCompilerFactory.class.getClassLoader();
-
- /*
- * This method is static so it can be exercised during initialization.
- */
private CompilationLevel adjustCompilationLevelInternal(Class<?> declaringClass, String name, String signature, CompilationLevel level) {
if (compileGraalWithC1Only) {
if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
- if (JDK9Method.Java8OrEarlier) {
- if (JVMCI_LOADER != null) {
- // When running with +UseJVMCIClassLoader all classes in
- // the JVMCI loader should be compiled with C1.
- try {
- if (declaringClass.getClassLoader() == JVMCI_LOADER) {
- return CompilationLevel.Simple;
- }
- } catch (SecurityException e) {
- // This is definitely not a JVMCI or Graal class
- }
- } else {
- // JVMCI and Graal are on the bootclasspath so match based on the package.
- String declaringClassName = declaringClass.getName();
- if (declaringClassName.startsWith("jdk.vm.ci")) {
- return CompilationLevel.Simple;
- }
- if (declaringClassName.startsWith("org.graalvm.") &&
- (declaringClassName.startsWith("org.graalvm.compiler.") ||
- declaringClassName.startsWith("org.graalvm.collections.") ||
- declaringClassName.startsWith("org.graalvm.compiler.word.") ||
- declaringClassName.startsWith("org.graalvm.graphio."))) {
- return CompilationLevel.Simple;
- }
- if (declaringClassName.startsWith("com.oracle.graal") &&
- (declaringClassName.startsWith("com.oracle.graal.enterprise") ||
- declaringClassName.startsWith("com.oracle.graal.vector") ||
- declaringClassName.startsWith("com.oracle.graal.asm"))) {
- return CompilationLevel.Simple;
- }
- }
- } else {
- try {
- Object module = JDK9Method.getModule(declaringClass);
- if (jvmciModule == module || graalModule == module || compilerConfigurationModule == module) {
- return CompilationLevel.Simple;
- }
- } catch (Throwable e) {
- throw new InternalError(e);
- }
+ if (isGraalPredicate.apply(declaringClass)) {
+ return CompilationLevel.Simple;
}
}
}
@@ -258,11 +199,4 @@
}
return level;
}
-
- public Map<String, Object> mbeans() {
- HotSpotGraalCompiler compiler = createCompiler(HotSpotJVMCIRuntime.runtime());
- String name = "org.graalvm.compiler.hotspot:type=Options";
- Object bean = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMBean();
- return Collections.singletonMap(name, bean);
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import jdk.vm.ci.meta.MetaUtil;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.vm.ci.runtime.JVMCI;
-
-import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.options.OptionDescriptor;
-import org.graalvm.compiler.options.OptionDescriptors;
-import org.graalvm.compiler.options.OptionKey;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-
-public final class HotSpotGraalMBean implements javax.management.DynamicMBean {
- private static Object mBeanServerField;
- private final HotSpotGraalCompiler compiler;
- private final OptionValues options;
- private final EconomicMap<OptionKey<?>, Object> changes;
- private final EconomicSet<Dump> methodDumps;
- private volatile EconomicSet<Reference<ClassLoader>> loaders;
- private javax.management.ObjectName registered;
- private OptionValues cachedOptions;
-
- private HotSpotGraalMBean(HotSpotGraalCompiler compiler, OptionValues options) {
- this.compiler = compiler;
- this.options = options;
- this.changes = EconomicMap.create();
- this.methodDumps = EconomicSet.create();
- EconomicSet<Reference<ClassLoader>> systemLoaderSet = EconomicSet.create(RefEquivalence.INSTANCE);
- systemLoaderSet.add(new WeakReference<>(ClassLoader.getSystemClassLoader()));
- this.loaders = systemLoaderSet;
- }
-
- private static boolean isMXServerOn() {
- if (mBeanServerField == null) {
- try {
- final Field field = java.lang.management.ManagementFactory.class.getDeclaredField("platformMBeanServer");
- field.setAccessible(true);
- mBeanServerField = field;
- } catch (Exception ex) {
- mBeanServerField = java.lang.management.ManagementFactory.class;
- }
- }
- if (mBeanServerField instanceof Field) {
- try {
- return ((Field) mBeanServerField).get(null) != null;
- } catch (Exception ex) {
- return true;
- }
- } else {
- return false;
- }
- }
-
- public static HotSpotGraalMBean create(HotSpotGraalCompiler compiler) {
- OptionValues options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
- HotSpotGraalMBean mbean = new HotSpotGraalMBean(compiler, options);
- return mbean;
- }
-
- public javax.management.ObjectName ensureRegistered(boolean check) {
- for (int cnt = 0;; cnt++) {
- if (registered != null) {
- return registered;
- }
- if (check && !isMXServerOn()) {
- return null;
- }
- try {
- javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer();
- javax.management.ObjectName name = new javax.management.ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
- mbs.registerMBean(this, name);
- registered = name;
- break;
- } catch (javax.management.MalformedObjectNameException | javax.management.MBeanRegistrationException | javax.management.NotCompliantMBeanException ex) {
- throw new IllegalStateException(ex);
- } catch (javax.management.InstanceAlreadyExistsException ex) {
- continue;
- }
- }
- return registered;
- }
-
- public OptionValues optionsFor(OptionValues initialValues, ResolvedJavaMethod forMethod) {
- ensureRegistered(true);
- if (forMethod instanceof HotSpotResolvedJavaMethod) {
- HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) forMethod).getDeclaringClass();
- if (type instanceof HotSpotResolvedJavaType) {
- Class<?> clazz = ((HotSpotResolvedJavaType) type).mirror();
- Reference<ClassLoader> addNewRef = new WeakReference<>(clazz.getClassLoader());
- if (!loaders.contains(addNewRef)) {
- EconomicSet<Reference<ClassLoader>> newLoaders = EconomicSet.create(RefEquivalence.INSTANCE, loaders);
- newLoaders.add(addNewRef);
- this.loaders = newLoaders;
- }
- }
- }
- return currentMap(initialValues, forMethod);
- }
-
- private OptionValues currentMap(OptionValues initialValues, ResolvedJavaMethod method) {
- if (changes.isEmpty() && methodDumps.isEmpty()) {
- return initialValues;
- }
- OptionValues current = cachedOptions;
- if (current == null) {
- current = new OptionValues(initialValues, changes);
- cachedOptions = current;
- }
- if (method != null) {
- for (Dump request : methodDumps) {
- final String clazzName = method.getDeclaringClass().getName();
- if (method.getName().equals(request.method) && clazzName.equals(request.clazz)) {
- current = new OptionValues(current, DebugOptions.Dump, request.filter,
- DebugOptions.PrintGraphHost, request.host,
- DebugOptions.PrintBinaryGraphPort, request.port);
- break;
- }
- }
- }
- return current;
- }
-
- @Override
- public Object getAttribute(String attribute) {
- UnmodifiableEconomicMap<OptionKey<?>, Object> map = currentMap(options, null).getMap();
- for (OptionKey<?> k : map.getKeys()) {
- if (k.getName().equals(attribute)) {
- return map.get(k);
- }
- }
- return null;
- }
-
- @Override
- public void setAttribute(javax.management.Attribute attribute) throws javax.management.AttributeNotFoundException {
- javax.management.Attribute newAttr = setImpl(attribute);
- if (newAttr == null) {
- throw new javax.management.AttributeNotFoundException();
- }
- }
-
- private javax.management.Attribute setImpl(javax.management.Attribute attribute) {
- cachedOptions = null;
- for (OptionDescriptor option : allOptionDescriptors()) {
- if (option.getName().equals(attribute.getName())) {
- changes.put(option.getOptionKey(), attribute.getValue());
- return attribute;
- }
- }
- return null;
- }
-
- @Override
- public javax.management.AttributeList getAttributes(String[] names) {
- javax.management.AttributeList list = new javax.management.AttributeList();
- for (String name : names) {
- Object value = getAttribute(name);
- if (value != null) {
- list.add(new javax.management.Attribute(name, value));
- }
- }
- return list;
- }
-
- @Override
- public javax.management.AttributeList setAttributes(javax.management.AttributeList attributes) {
- javax.management.AttributeList setOk = new javax.management.AttributeList();
- for (javax.management.Attribute attr : attributes.asList()) {
- javax.management.Attribute newAttr = setImpl(attr);
- if (newAttr != null) {
- setOk.add(newAttr);
- }
- }
- return setOk;
- }
-
- @Override
- public Object invoke(String actionName, Object[] params, String[] signature) throws javax.management.MBeanException, javax.management.ReflectionException {
- if ("dumpMethod".equals(actionName)) {
- try {
- String className = param(params, 0, "className", String.class, null);
- String methodName = param(params, 1, "methodName", String.class, null);
- String filter = param(params, 2, "filter", String.class, ":3");
- String host = param(params, 3, "host", String.class, "localhost");
- Number port = param(params, 4, "port", Number.class, 4445);
- dumpMethod(className, methodName, filter, host, port.intValue());
- } catch (Exception ex) {
- throw new javax.management.ReflectionException(ex);
- }
- }
- return null;
- }
-
- private static <T> T param(Object[] arr, int index, String name, Class<T> type, T defaultValue) {
- Object value = arr.length > index ? arr[index] : null;
- if (value == null || (value instanceof String && ((String) value).isEmpty())) {
- if (defaultValue == null) {
- throw new IllegalArgumentException(name + " must be specified");
- }
- value = defaultValue;
- }
- if (type.isInstance(value)) {
- return type.cast(value);
- }
- throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
- }
-
- public void dumpMethod(String className, String methodName, String filter, String host, int port) throws javax.management.MBeanException {
- String jvmName = MetaUtil.toInternalName(className);
- methodDumps.add(new Dump(host, port, jvmName, methodName, filter));
-
- ClassNotFoundException last = null;
- EconomicSet<Class<?>> found = EconomicSet.create();
- Iterator<Reference<ClassLoader>> it = loaders.iterator();
- while (it.hasNext()) {
- Reference<ClassLoader> ref = it.next();
- ClassLoader loader = ref.get();
- if (loader == null) {
- it.remove();
- continue;
- }
- try {
- Class<?> clazz = Class.forName(className, false, loader);
- if (found.add(clazz)) {
- ResolvedJavaType type = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(clazz);
- if (compiler != null) {
- for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
- if (methodName.equals(method.getName()) && method instanceof HotSpotResolvedJavaMethod) {
- HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method;
- compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false);
- }
- }
- }
- }
- } catch (ClassNotFoundException ex) {
- last = ex;
- }
- }
- if (found.isEmpty()) {
- throw new javax.management.MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
- }
- }
-
- @Override
- public javax.management.MBeanInfo getMBeanInfo() {
- List<javax.management.MBeanAttributeInfo> attrs = new ArrayList<>();
- for (OptionDescriptor descr : allOptionDescriptors()) {
- attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
- }
- javax.management.MBeanOperationInfo[] ops = {
- new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
- new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
- new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
- }, "void", javax.management.MBeanOperationInfo.ACTION),
- new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
- new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
- new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
- new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
- }, "void", javax.management.MBeanOperationInfo.ACTION),
- new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
- new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
- new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
- new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
- new javax.management.MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
- new javax.management.MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
- }, "void", javax.management.MBeanOperationInfo.ACTION)
- };
-
- return new javax.management.MBeanInfo(
- HotSpotGraalMBean.class.getName(),
- "Graal",
- attrs.toArray(new javax.management.MBeanAttributeInfo[attrs.size()]),
- null, ops, null);
- }
-
- private static Iterable<OptionDescriptor> allOptionDescriptors() {
- List<OptionDescriptor> arr = new ArrayList<>();
- for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
- for (OptionDescriptor descr : set) {
- arr.add(descr);
- }
- }
- return arr;
- }
-
- private static final class Dump {
- final String host;
- final int port;
- final String clazz;
- final String method;
- final String filter;
-
- Dump(String host, int port, String clazz, String method, String filter) {
- this.host = host;
- this.port = port;
- this.clazz = clazz;
- this.method = method;
- this.filter = filter;
- }
- }
-
- private static final class RefEquivalence extends Equivalence {
- static final Equivalence INSTANCE = new RefEquivalence();
-
- private RefEquivalence() {
- }
-
- @Override
- public boolean equals(Object a, Object b) {
- Reference<?> refA = (Reference<?>) a;
- Reference<?> refB = (Reference<?>) b;
- return Objects.equals(refA.get(), refB.get());
- }
-
- @Override
- public int hashCode(Object o) {
- Reference<?> ref = (Reference<?>) o;
- Object obj = ref.get();
- return obj == null ? 0 : obj.hashCode();
- }
-
- }
-}
--- /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/HotSpotGraalManagementRegistration.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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;
+
+/**
+ * Communicates with an MBean providing a JMX interface to a {@link HotSpotGraalRuntime} instance.
+ * The MBean will be dynamically created when a JMX client attaches or some other event causes the
+ * platform MBean server to be started.
+ */
+public interface HotSpotGraalManagementRegistration {
+
+ /**
+ * Completes the initialization of this registration by recording the
+ * {@link HotSpotGraalRuntime} the MBean will provide an JMX interface to.
+ */
+ void initialize(HotSpotGraalRuntime runtime);
+
+ /**
+ * Polls this registration to see if the MBean is registered in a MBean server.
+ *
+ * @param sync synchronize with other threads that may be processing this registration. This is
+ * useful when the caller knows the server is active (e.g., it has a reference to
+ * server) and expects this poll to therefore return a non-null value.
+ * @return an {@link javax.management.ObjectName} that can be used to access the MBean or
+ * {@code null} if the MBean has not been registered with an MBean server (e.g., no JMX
+ * client has attached to the VM)
+ */
+ Object poll(boolean sync);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,14 +30,12 @@
import java.util.Map;
import java.util.Properties;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.options.OptionValuesAccess;
import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.compiler.serviceprovider.ServiceProvider;
import jdk.vm.ci.common.InitTimer;
@@ -45,8 +43,7 @@
* The {@link #HOTSPOT_OPTIONS} value contains the options values initialized in a HotSpot VM. The
* values are set via system properties with the {@value #GRAAL_OPTION_PROPERTY_PREFIX} prefix.
*/
-@ServiceProvider(OptionValuesAccess.class)
-public class HotSpotGraalOptionValues implements OptionValuesAccess {
+public class HotSpotGraalOptionValues {
/**
* The name of the system property specifying a file containing extra Graal option settings.
@@ -131,9 +128,4 @@
return new OptionValues(values);
}
}
-
- @Override
- public OptionValues getOptions() {
- return HOTSPOT_OPTIONS;
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,9 +33,12 @@
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.api.runtime.GraalRuntime;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
@@ -45,6 +48,7 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugContext.Description;
import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
import org.graalvm.compiler.debug.GlobalMetrics;
import org.graalvm.compiler.debug.GraalError;
@@ -54,19 +58,31 @@
import org.graalvm.compiler.hotspot.debug.BenchmarkCounters;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.nodes.spi.StampProvider;
+import org.graalvm.compiler.options.EnumOptionKey;
+import org.graalvm.compiler.options.OptionDescriptor;
+import org.graalvm.compiler.options.OptionDescriptors;
+import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.options.OptionsParser;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.replacements.SnippetCounter;
import org.graalvm.compiler.replacements.SnippetCounter.Group;
import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.code.stack.StackIntrospection;
import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
import jdk.vm.ci.runtime.JVMCIBackend;
//JaCoCo Exclude
@@ -88,6 +104,7 @@
return true;
}
+ private final String runtimeName;
private final HotSpotBackend hostBackend;
private final GlobalMetrics metricValues = new GlobalMetrics();
private final List<SnippetCounter.Group> snippetCounterGroups;
@@ -96,25 +113,42 @@
private final GraalHotSpotVMConfig config;
- private final OptionValues options;
+ /**
+ * The options can be {@linkplain #setOptionValues(String[], String[]) updated} by external
+ * interfaces such as JMX. This comes with the risk that inconsistencies can arise as an
+ * {@link OptionValues} object can be cached by various parts of Graal instead of always
+ * obtaining them from this object. However, concurrent updates are never lost.
+ */
+ private AtomicReference<OptionValues> optionsRef = new AtomicReference<>();
+
+ private final HotSpotGraalCompiler compiler;
+
private final DiagnosticsOutputDirectory outputDirectory;
private final Map<ExceptionAction, Integer> compilationProblemsPerAction;
- private final HotSpotGraalMBean mBean;
/**
+ * @param nameQualifier a qualifier to be added to this runtime's {@linkplain #getName() name}
* @param compilerConfigurationFactory factory for the compiler configuration
* {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)}
*/
@SuppressWarnings("try")
- HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) {
+ HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) {
+ this.runtimeName = getClass().getSimpleName() + ":" + nameQualifier;
HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
config = GeneratePIC.getValue(initialOptions) ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store);
// Only set HotSpotPrintInlining if it still has its default value (false).
if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) {
- options = new OptionValues(initialOptions, HotSpotPrintInlining, true);
+ optionsRef.set(new OptionValues(initialOptions, HotSpotPrintInlining, true));
} else {
- options = initialOptions;
+ optionsRef.set(initialOptions);
+ }
+ OptionValues options = optionsRef.get();
+
+ if (config.useCMSGC) {
+ // Graal doesn't work with the CMS collector (e.g. GR-6777)
+ // and is deprecated (http://openjdk.java.net/jeps/291).
+ throw new GraalError("Graal does not support the CMS collector");
}
outputDirectory = new DiagnosticsOutputDirectory(options);
@@ -122,8 +156,11 @@
snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
- HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions);
- this.mBean = createHotSpotGraalMBean(compiler);
+ compiler = new HotSpotGraalCompiler(jvmciRuntime, this, options);
+ management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false);
+ if (management != null) {
+ management.initialize(this);
+ }
BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
@@ -172,14 +209,6 @@
bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
}
- private static HotSpotGraalMBean createHotSpotGraalMBean(HotSpotGraalCompiler compiler) {
- try {
- return HotSpotGraalMBean.create(compiler);
- } catch (LinkageError ex) {
- return null;
- }
- }
-
private HotSpotBackend registerBackend(HotSpotBackend backend) {
Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
HotSpotBackend oldValue = backends.put(arch, backend);
@@ -199,24 +228,35 @@
@Override
public DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable<DebugHandlersFactory> factories) {
+ if (management != null && management.poll(false) != null) {
+ if (compilable instanceof HotSpotResolvedJavaMethod) {
+ HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) compilable).getDeclaringClass();
+ if (type instanceof HotSpotResolvedJavaType) {
+ Class<?> clazz = ((HotSpotResolvedJavaType) type).mirror();
+ try {
+ ClassLoader cl = clazz.getClassLoader();
+ if (cl != null) {
+ loaders.add(cl);
+ }
+ } catch (SecurityException e) {
+ // This loader can obviously not be used for resolving class names
+ }
+ }
+ }
+ }
Description description = new Description(compilable, compilationId.toString(CompilationIdentifier.Verbosity.ID));
return DebugContext.create(compilationOptions, description, metricValues, DEFAULT_LOG_STREAM, factories);
}
@Override
public OptionValues getOptions() {
- return mBean == null ? options : mBean.optionsFor(options, null);
+ return optionsRef.get();
}
@Override
- public OptionValues getOptions(ResolvedJavaMethod forMethod) {
- return mBean == null ? options : mBean.optionsFor(options, forMethod);
- }
-
- @Override
- public Group createSnippetCounterGroup(String name) {
+ public Group createSnippetCounterGroup(String groupName) {
if (snippetCounterGroups != null) {
- Group group = new Group(name);
+ Group group = new Group(groupName);
snippetCounterGroups.add(group);
return group;
}
@@ -225,7 +265,7 @@
@Override
public String getName() {
- return getClass().getSimpleName();
+ return runtimeName;
}
@SuppressWarnings("unchecked")
@@ -234,7 +274,7 @@
if (clazz == RuntimeProvider.class) {
return (T) this;
} else if (clazz == OptionValues.class) {
- return (T) options;
+ return (T) optionsRef.get();
} else if (clazz == StackIntrospection.class) {
return (T) this;
} else if (clazz == SnippetReflectionProvider.class) {
@@ -265,14 +305,14 @@
* @param phase the execution phase being entered
*/
void phaseTransition(String phase) {
- if (Options.UseCompilationStatistics.getValue(options)) {
+ if (Options.UseCompilationStatistics.getValue(optionsRef.get())) {
CompilationStatistics.clear(phase);
}
}
void shutdown() {
shutdown = true;
- metricValues.print(options);
+ metricValues.print(optionsRef.get());
phaseTransition("final");
@@ -281,7 +321,7 @@
TTY.out().out().println(group);
}
}
- BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime);
+ BenchmarkCounters.shutdown(runtime(), optionsRef.get(), runtimeStartTime);
outputDirectory.close();
}
@@ -317,7 +357,193 @@
return compilationProblemsPerAction;
}
- Object getMBean() {
- return mBean;
+ // ------- Management interface ---------
+
+ private final HotSpotGraalManagementRegistration management;
+
+ /**
+ * @returns the management object for this runtime or {@code null}
+ */
+ public HotSpotGraalManagementRegistration getManagement() {
+ return management;
+ }
+
+ /**
+ * Set of weak references to {@link ClassLoader}s available for resolving class names present in
+ * management {@linkplain #invokeManagementAction(String, Object[]) action} arguments.
+ */
+ private final WeakClassLoaderSet loaders = new WeakClassLoaderSet(ClassLoader.getSystemClassLoader());
+
+ /**
+ * Sets or updates this object's {@linkplain #getOptions() options} from {@code names} and
+ * {@code values}.
+ *
+ * @param values the values to set. The empty string represents {@code null} which resets an
+ * option to its default value. For string type options, a non-empty value must be
+ * enclosed in double quotes.
+ * @return an array of Strings where the element at index i is {@code names[i]} if setting the
+ * denoted option succeeded, {@code null} if the option is unknown otherwise an error
+ * message describing the failure to set the option
+ */
+ public String[] setOptionValues(String[] names, String[] values) {
+ EconomicMap<String, OptionDescriptor> optionDescriptors = getOptionDescriptors();
+ EconomicMap<OptionKey<?>, Object> newValues = EconomicMap.create(names.length);
+ EconomicSet<OptionKey<?>> resetValues = EconomicSet.create(names.length);
+ String[] result = new String[names.length];
+ for (int i = 0; i < names.length; i++) {
+ String name = names[i];
+ OptionDescriptor option = optionDescriptors.get(name);
+ if (option != null) {
+ String svalue = values[i];
+ Class<?> optionValueType = option.getOptionValueType();
+ OptionKey<?> optionKey = option.getOptionKey();
+ if (svalue == null || svalue.isEmpty() && !(optionKey instanceof EnumOptionKey)) {
+ resetValues.add(optionKey);
+ result[i] = name;
+ } else {
+ String valueToParse;
+ if (optionValueType == String.class) {
+ if (svalue.length() < 2 || svalue.charAt(0) != '"' || svalue.charAt(svalue.length() - 1) != '"') {
+ result[i] = "Invalid value for String option '" + name + "': must be the empty string or be enclosed in double quotes: " + svalue;
+ continue;
+ } else {
+ valueToParse = svalue.substring(1, svalue.length() - 1);
+ }
+ } else {
+ valueToParse = svalue;
+ }
+ try {
+ OptionsParser.parseOption(name, valueToParse, newValues, OptionsParser.getOptionsLoader());
+ result[i] = name;
+ } catch (IllegalArgumentException e) {
+ result[i] = e.getMessage();
+ continue;
+ }
+ }
+ } else {
+ result[i] = null;
+ }
+ }
+
+ OptionValues currentOptions;
+ OptionValues newOptions;
+ do {
+ currentOptions = optionsRef.get();
+ UnmodifiableMapCursor<OptionKey<?>, Object> cursor = currentOptions.getMap().getEntries();
+ while (cursor.advance()) {
+ OptionKey<?> key = cursor.getKey();
+ if (!resetValues.contains(key) && !newValues.containsKey(key)) {
+ newValues.put(key, OptionValues.decodeNull(cursor.getValue()));
+ }
+ }
+ newOptions = new OptionValues(newValues);
+ } while (!optionsRef.compareAndSet(currentOptions, newOptions));
+
+ return result;
+ }
+
+ /**
+ * Gets the values for the options corresponding to {@code names} encoded as strings. The empty
+ * string represents {@code null}. For string type options, non-{@code null} values will be
+ * enclosed in double quotes.
+ *
+ * @param names a list of option names
+ * @return the values for each named option. If an element in {@code names} does not denote an
+ * existing option, the corresponding element in the returned array will be {@code null}
+ */
+ public String[] getOptionValues(String... names) {
+ String[] values = new String[names.length];
+ EconomicMap<String, OptionDescriptor> optionDescriptors = getOptionDescriptors();
+ for (int i = 0; i < names.length; i++) {
+ OptionDescriptor option = optionDescriptors.get(names[i]);
+ if (option != null) {
+ OptionKey<?> optionKey = option.getOptionKey();
+ Object value = optionKey.getValue(getOptions());
+ String svalue;
+ if (option.getOptionValueType() == String.class && value != null) {
+ svalue = "\"" + value + "\"";
+ } else if (value == null) {
+ svalue = "";
+ } else {
+ svalue = String.valueOf(value);
+ }
+ values[i] = svalue;
+ } else {
+ // null denotes the option does not exist
+ values[i] = null;
+ }
+ }
+ return values;
+ }
+
+ private static EconomicMap<String, OptionDescriptor> getOptionDescriptors() {
+ EconomicMap<String, OptionDescriptor> result = EconomicMap.create();
+ for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
+ for (OptionDescriptor option : set) {
+ result.put(option.getName(), option);
+ }
+ }
+ return result;
+ }
+
+ private void dumpMethod(String className, String methodName, String filter, String host, int port) throws Exception {
+ EconomicSet<ClassNotFoundException> failures = EconomicSet.create();
+ EconomicSet<Class<?>> found = loaders.resolve(className, failures);
+ if (found.isEmpty()) {
+ ClassNotFoundException cause = failures.isEmpty() ? new ClassNotFoundException(className) : failures.iterator().next();
+ throw new Exception("Cannot find class " + className + " to schedule recompilation", cause);
+ }
+ for (Class<?> clazz : found) {
+ ResolvedJavaType type = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(clazz);
+ for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+ if (methodName.equals(method.getName()) && method instanceof HotSpotResolvedJavaMethod) {
+ HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method;
+ dumpMethod(hotSpotMethod, filter, host, port);
+ }
+ }
+ }
+ }
+
+ private void dumpMethod(HotSpotResolvedJavaMethod hotSpotMethod, String filter, String host, int port) throws Exception {
+ EconomicMap<OptionKey<?>, Object> extra = EconomicMap.create();
+ extra.put(DebugOptions.Dump, filter);
+ extra.put(DebugOptions.PrintGraphHost, host);
+ extra.put(DebugOptions.PrintBinaryGraphPort, port);
+ OptionValues compileOptions = new OptionValues(getOptions(), extra);
+ compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false, compileOptions);
+ }
+
+ public Object invokeManagementAction(String actionName, Object[] params) throws Exception {
+ if ("dumpMethod".equals(actionName)) {
+ if (params.length != 0 && params[0] instanceof HotSpotResolvedJavaMethod) {
+ HotSpotResolvedJavaMethod method = param(params, 0, "method", HotSpotResolvedJavaMethod.class, null);
+ String filter = param(params, 1, "filter", String.class, ":3");
+ String host = param(params, 2, "host", String.class, "localhost");
+ Number port = param(params, 3, "port", Number.class, 4445);
+ dumpMethod(method, filter, host, port.intValue());
+ } else {
+ String className = param(params, 0, "className", String.class, null);
+ String methodName = param(params, 1, "methodName", String.class, null);
+ String filter = param(params, 2, "filter", String.class, ":3");
+ String host = param(params, 3, "host", String.class, "localhost");
+ Number port = param(params, 4, "port", Number.class, 4445);
+ dumpMethod(className, methodName, filter, host, port.intValue());
+ }
+ }
+ return null;
+ }
+
+ private static <T> T param(Object[] arr, int index, String name, Class<T> type, T defaultValue) {
+ Object value = arr.length > index ? arr[index] : null;
+ if (value == null || (value instanceof String && ((String) value).isEmpty())) {
+ if (defaultValue == null) {
+ throw new IllegalArgumentException(name + " must be specified");
+ }
+ value = defaultValue;
+ }
+ if (type.isInstance(value)) {
+ return type.cast(value);
+ }
+ throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,16 +27,15 @@
import org.graalvm.compiler.api.runtime.GraalRuntime;
import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
-import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.SnippetCounter.Group;
import org.graalvm.compiler.runtime.RuntimeProvider;
import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
//JaCoCo Exclude
@@ -77,14 +76,6 @@
OptionValues getOptions();
/**
- * Gets the option values associated with this runtime that are applicable for a given method.
- *
- * @param forMethod the method we are seeking for options for
- * @return the options applicable for compiling {@code method}
- */
- OptionValues getOptions(ResolvedJavaMethod forMethod);
-
- /**
* Determines if the VM is currently bootstrapping the JVMCI compiler.
*/
boolean isBootstrapping();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
*/
package org.graalvm.compiler.hotspot;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.lir.LIR;
--- /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/IsGraalPredicate.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
+
+/**
+ * Determines if a given class is a JVMCI or Graal class for the purpose of
+ * {@link HotSpotGraalCompilerFactory.Options#CompileGraalWithC1Only}.
+ */
+public class IsGraalPredicate {
+ /**
+ * Module containing {@link HotSpotJVMCICompilerFactory}.
+ */
+ private final Module jvmciModule;
+
+ /**
+ * Module containing {@link HotSpotGraalCompilerFactory}.
+ */
+ private final Module graalModule;
+
+ /**
+ * Module containing the {@linkplain CompilerConfigurationFactory#selectFactory selected}
+ * configuration.
+ */
+ private Module compilerConfigurationModule;
+
+ public IsGraalPredicate() {
+ jvmciModule = HotSpotJVMCICompilerFactory.class.getModule();
+ graalModule = HotSpotGraalCompilerFactory.class.getModule();
+ }
+
+ void onCompilerConfigurationFactorySelection(CompilerConfigurationFactory factory) {
+ compilerConfigurationModule = factory.getClass().getModule();
+ }
+
+ boolean apply(Class<?> declaringClass) {
+ Module module = declaringClass.getModule();
+ return jvmciModule == module || graalModule == module || compilerConfigurationModule == module;
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,15 +27,19 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
+import java.util.List;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
/**
- * An option that encapsulates and configures a print stream.
+ * An option for a configurable file name that can also open a {@link PrintStream} on the file. If
+ * no value is given for the option, the stream will output to HotSpot's
+ * {@link HotSpotJVMCIRuntimeProvider#getLogStream() log} stream
*/
public class PrintStreamOptionKey extends OptionKey<String> {
@@ -44,27 +48,13 @@
}
/**
- * Replace any instance of %p with an identifying name. Try to get it from the RuntimeMXBean
- * name.
- *
- * @return the name of the file to log to
+ * @return {@code nameTemplate} with all instances of %p replaced by
+ * {@link GraalServices#getExecutionID()} and %t by {@link System#currentTimeMillis()}
*/
- private String getFilename(OptionValues options) {
- String name = getValue(options);
+ private static String makeFilename(String nameTemplate) {
+ String name = nameTemplate;
if (name.contains("%p")) {
- try {
- String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
- int index = runtimeName.indexOf('@');
- if (index != -1) {
- long pid = Long.parseLong(runtimeName.substring(0, index));
- runtimeName = Long.toString(pid);
- }
- name = name.replaceAll("%p", runtimeName);
- } catch (NumberFormatException e) {
-
- } catch (LinkageError err) {
- name = String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
- }
+ name = name.replaceAll("%p", GraalServices.getExecutionID());
}
if (name.contains("%t")) {
name = name.replaceAll("%t", String.valueOf(System.currentTimeMillis()));
@@ -118,22 +108,26 @@
* will output to HotSpot's {@link HotSpotJVMCIRuntimeProvider#getLogStream() log} stream.
*/
public PrintStream getStream(OptionValues options) {
- if (getValue(options) != null) {
+ String nameTemplate = getValue(options);
+ if (nameTemplate != null) {
+ String name = makeFilename(nameTemplate);
try {
final boolean enableAutoflush = true;
- PrintStream ps = new PrintStream(new FileOutputStream(getFilename(options)), enableAutoflush);
+ PrintStream ps = new PrintStream(new FileOutputStream(name), enableAutoflush);
/*
* Add the JVM and Java arguments to the log file to help identity it.
*/
- String inputArguments = String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
- ps.println("VM Arguments: " + inputArguments);
+ List<String> inputArguments = GraalServices.getInputArguments();
+ if (inputArguments != null) {
+ ps.println("VM Arguments: " + String.join(" ", inputArguments));
+ }
String cmd = System.getProperty("sun.java.command");
if (cmd != null) {
ps.println("sun.java.command=" + cmd);
}
return ps;
} catch (FileNotFoundException e) {
- throw new RuntimeException("couldn't open file: " + getValue(options), e);
+ throw new RuntimeException("couldn't open file: " + name, e);
}
} else {
return new PrintStream(new DelayedOutputStream());
--- /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/WeakClassLoaderSet.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.UnaryOperator;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+
+/**
+ * A set of weak references to {@link ClassLoader}s.
+ */
+public final class WeakClassLoaderSet {
+
+ /**
+ * Copy-on-write set of loaders.
+ */
+ private volatile AtomicReference<EconomicSet<Reference<ClassLoader>>> loaders = new AtomicReference<>(EconomicSet.create(RefEquivalence.INSTANCE));
+
+ public WeakClassLoaderSet(ClassLoader... initialEntries) {
+ for (ClassLoader loader : initialEntries) {
+ loaders.get().add(new WeakReference<>(loader));
+ }
+ }
+
+ /**
+ * Adds {@code loader} to this set.
+ */
+ public void add(ClassLoader loader) {
+ Reference<ClassLoader> addNewRef = new WeakReference<>(loader);
+ EconomicSet<Reference<ClassLoader>> currentLoaders = loaders.get();
+ if (!currentLoaders.contains(addNewRef)) {
+ this.loaders.getAndUpdate(new UnaryOperator<EconomicSet<Reference<ClassLoader>>>() {
+ @Override
+ public EconomicSet<Reference<ClassLoader>> apply(EconomicSet<Reference<ClassLoader>> t) {
+ EconomicSet<Reference<ClassLoader>> newLoaders = EconomicSet.create(RefEquivalence.INSTANCE, t);
+ newLoaders.add(addNewRef);
+ return newLoaders;
+ }
+ });
+ }
+ }
+
+ /**
+ * Tries to resolve {@code className} to {@link Class} instances with the loaders in this set.
+ *
+ * @param className name of a class to resolve
+ * @param resolutionFailures all resolution failures are returned in this set
+ * @return the set of classes successfully resolved
+ */
+ public EconomicSet<Class<?>> resolve(String className, EconomicSet<ClassNotFoundException> resolutionFailures) {
+ EconomicSet<Class<?>> found = EconomicSet.create();
+ Iterator<Reference<ClassLoader>> it = loaders.get().iterator();
+ while (it.hasNext()) {
+ Reference<ClassLoader> ref = it.next();
+ ClassLoader loader = ref.get();
+ if (loader == null) {
+ it.remove();
+ continue;
+ }
+ try {
+ Class<?> clazz = Class.forName(className, false, loader);
+ found.add(clazz);
+ } catch (ClassNotFoundException ex) {
+ resolutionFailures.add(ex);
+ }
+ }
+ return found;
+ }
+
+ private static final class RefEquivalence extends Equivalence {
+ static final Equivalence INSTANCE = new RefEquivalence();
+
+ private RefEquivalence() {
+ }
+
+ @Override
+ public boolean equals(Object a, Object b) {
+ Reference<?> refA = (Reference<?>) a;
+ Reference<?> refB = (Reference<?>) b;
+ Object referentA = refA.get();
+ Object referentB = refB.get();
+ return Objects.equals(referentA, referentB);
+ }
+
+ @Override
+ public int hashCode(Object o) {
+ Reference<?> ref = (Reference<?>) o;
+ Object obj = ref.get();
+ return obj == null ? 0 : obj.hashCode();
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.common.AddressLoweringPhase;
+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.tiers.LowTierContext;
@@ -41,10 +41,10 @@
*/
public class AddressLoweringHotSpotSuitesProvider extends HotSpotSuitesProvider {
- private final AddressLoweringPhase.AddressLowering addressLowering;
+ private final Phase addressLowering;
public AddressLoweringHotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime,
- AddressLoweringPhase.AddressLowering addressLowering) {
+ Phase addressLowering) {
super(defaultSuitesCreator, config, runtime);
this.addressLowering = addressLowering;
}
@@ -57,7 +57,7 @@
if (findPhase == null) {
findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class);
}
- findPhase.add(new AddressLoweringPhase(addressLowering));
+ 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 Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_LAYOUT_HELPER_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import java.lang.ref.Reference;
@@ -155,7 +155,7 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider;
import org.graalvm.compiler.replacements.nodes.AssertionNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
@@ -43,7 +43,7 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CodeCacheProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
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.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MutableCallSite;
@@ -100,10 +100,9 @@
import org.graalvm.compiler.replacements.ReplacementsImpl;
import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins;
import org.graalvm.compiler.serviceprovider.GraalServices;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
import org.graalvm.compiler.word.WordOperationPlugin;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -160,7 +159,7 @@
@Override
public void run() {
BytecodeProvider replacementBytecodeProvider = replacements.getDefaultReplacementBytecodeProvider();
- registerObjectPlugins(invocationPlugins, options, replacementBytecodeProvider);
+ registerObjectPlugins(invocationPlugins, options, config, replacementBytecodeProvider);
registerClassPlugins(plugins, config, replacementBytecodeProvider);
registerSystemPlugins(invocationPlugins, foreignCalls);
registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacementBytecodeProvider);
@@ -186,7 +185,7 @@
return plugins;
}
- private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, BytecodeProvider bytecodeProvider) {
+ private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
Registration r = new Registration(plugins, Object.class, bytecodeProvider);
if (!GeneratePIC.getValue(options)) {
// FIXME: clone() requires speculation and requires a fix in here (to check that
@@ -210,6 +209,12 @@
});
}
r.registerMethodSubstitution(ObjectSubstitutions.class, "hashCode", Receiver.class);
+ if (config.inlineNotify()) {
+ r.registerMethodSubstitution(ObjectSubstitutions.class, "notify", Receiver.class);
+ }
+ if (config.inlineNotifyAll()) {
+ r.registerMethodSubstitution(ObjectSubstitutions.class, "notifyAll", Receiver.class);
+ }
}
private static void registerClassPlugins(Plugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
@@ -440,7 +445,7 @@
public static final String constantPoolClass;
static {
- if (JDK9Method.Java8OrEarlier) {
+ if (Java8OrEarlier) {
cbcEncryptName = "encrypt";
cbcDecryptName = "decrypt";
aesEncryptName = "encryptBlock";
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -97,11 +97,11 @@
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.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import java.util.EnumMap;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.debug.GraalError;
@@ -124,7 +124,7 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
@@ -140,6 +140,9 @@
public static final ForeignCallDescriptor JAVA_TIME_MILLIS = new ForeignCallDescriptor("javaTimeMillis", long.class);
public static final ForeignCallDescriptor JAVA_TIME_NANOS = new ForeignCallDescriptor("javaTimeNanos", long.class);
+ public static final ForeignCallDescriptor NOTIFY = new ForeignCallDescriptor("object_notify", boolean.class, Object.class);
+ public static final ForeignCallDescriptor NOTIFY_ALL = new ForeignCallDescriptor("object_notifyAll", boolean.class, Object.class);
+
public HotSpotHostForeignCallsProvider(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache,
WordTypes wordTypes) {
super(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes);
@@ -292,6 +295,8 @@
linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any());
linkForeignCall(options, providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
+ linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
+ linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
linkForeignCall(options, providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
linkForeignCall(options, providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,15 +22,9 @@
*/
package org.graalvm.compiler.hotspot.meta;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import java.lang.reflect.Type;
-import java.lang.invoke.MethodHandle;
-import java.lang.reflect.Type;
-import java.util.Set;
-
-import org.graalvm.collections.EconomicSet;
import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -43,7 +37,6 @@
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
import org.graalvm.compiler.replacements.nodes.MacroNode;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
import jdk.vm.ci.meta.JavaKind;
@@ -54,18 +47,11 @@
*/
final class HotSpotInvocationPlugins extends InvocationPlugins {
private final GraalHotSpotVMConfig config;
- private final EconomicSet<Object> trustedModules;
- private final ClassLoader extLoader;
+ private final IntrinsificationPredicate intrinsificationPredicate;
HotSpotInvocationPlugins(GraalHotSpotVMConfig config, CompilerConfiguration compilerConfiguration) {
this.config = config;
- if (Java8OrEarlier) {
- extLoader = getExtLoader();
- trustedModules = null;
- } else {
- extLoader = null;
- trustedModules = initTrustedModules(compilerConfiguration);
- }
+ intrinsificationPredicate = new IntrinsificationPredicate(compilerConfiguration);
}
@Override
@@ -114,79 +100,12 @@
return type != null && "Ljava/lang/Class;".equals(type.getName());
}
- /**
- * {@inheritDoc}
- *
- * On JDK 8, only classes loaded by the boot, JVMCI or extension class loaders are trusted.
- *
- * On JDK 9 and later, only classes in the {@link CompilerConfiguration} defining module or any
- * of its module dependencies are trusted.
- */
@Override
public boolean canBeIntrinsified(ResolvedJavaType declaringClass) {
if (declaringClass instanceof HotSpotResolvedJavaType) {
- Class<?> javaClass = ((HotSpotResolvedJavaType) declaringClass).mirror();
- if (Java8OrEarlier) {
- ClassLoader cl = javaClass.getClassLoader();
- return cl == null || cl == getClass().getClassLoader() || cl == extLoader;
- } else {
- Object module = JDK9Method.getModule(javaClass);
- return trustedModules.contains(module);
- }
+ HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) declaringClass;
+ return intrinsificationPredicate.apply(type.mirror());
}
return false;
}
-
- private static ClassLoader getExtLoader() {
- try {
- Object launcher = Class.forName("sun.misc.Launcher").getMethod("getLauncher").invoke(null);
- ClassLoader appLoader = (ClassLoader) launcher.getClass().getMethod("getClassLoader").invoke(launcher);
- ClassLoader extLoader = appLoader.getParent();
- assert extLoader.getClass().getName().equals("sun.misc.Launcher$ExtClassLoader") : extLoader;
- return extLoader;
- } catch (Exception e) {
- throw new GraalError(e);
- }
- }
-
- /**
- * Gets the set of modules whose methods can be intrinsified. This set is the module owning the
- * class of {@code compilerConfiguration} and all its dependencies.
- */
- private static EconomicSet<Object> initTrustedModules(CompilerConfiguration compilerConfiguration) throws GraalError {
- try {
- EconomicSet<Object> res = EconomicSet.create();
- Object compilerConfigurationModule = JDK9Method.getModule(compilerConfiguration.getClass());
- res.add(compilerConfigurationModule);
- Class<?> moduleClass = compilerConfigurationModule.getClass();
- Object layer = JDK9Method.lookupMethodHandle(moduleClass, "getLayer").invoke(compilerConfigurationModule);
- Class<? extends Object> layerClass = layer.getClass();
- MethodHandle getName = JDK9Method.lookupMethodHandle(moduleClass, "getName");
- Set<Object> modules = (Set<Object>) JDK9Method.lookupMethodHandle(layerClass, "modules").invoke(layer);
- Object descriptor = JDK9Method.lookupMethodHandle(moduleClass, "getDescriptor").invoke(compilerConfigurationModule);
- Class<?> moduleDescriptorClass = descriptor.getClass();
- Set<Object> requires = (Set<Object>) JDK9Method.lookupMethodHandle(moduleDescriptorClass, "requires").invoke(descriptor);
- boolean isAutomatic = (Boolean) JDK9Method.lookupMethodHandle(moduleDescriptorClass, "isAutomatic").invoke(descriptor);
- if (isAutomatic) {
- throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
- getName.invoke(compilerConfigurationModule), compilerConfiguration.getClass().getName()));
- }
- MethodHandle requireNameGetter = null;
- for (Object require : requires) {
- if (requireNameGetter == null) {
- requireNameGetter = JDK9Method.lookupMethodHandle(require.getClass(), "name");
- }
- String name = (String) requireNameGetter.invoke(require);
- for (Object module : modules) {
- String moduleName = (String) getName.invoke(module);
- if (moduleName.equals(name)) {
- res.add(module);
- }
- }
- }
- return res;
- } catch (Throwable e) {
- throw new GraalError(e);
- }
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotUnsafeSubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotUnsafeSubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,14 +22,14 @@
*/
package org.graalvm.compiler.hotspot.meta;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.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.hotspot.nodes.ComputeObjectAddressNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
@ClassSubstitution(className = {"jdk.internal.misc.Unsafe", "sun.misc.Unsafe"})
public class HotSpotUnsafeSubstitutions {
@@ -41,7 +41,7 @@
static void copyMemory(Object receiver, Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) {
Word srcAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(srcBase, srcOffset));
Word dstAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(destBase, destOffset));
- Word size = Word.signed(bytes);
+ Word size = WordFactory.signed(bytes);
HotSpotBackend.unsafeArraycopy(srcAddr, dstAddr, size);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_EQ;
import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE;
import static org.graalvm.compiler.nodes.ConstantNode.forBoolean;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BridgeMethodUtils;
@@ -53,7 +53,7 @@
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.word.WordOperationPlugin;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- /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/IntrinsificationPredicate.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.meta;
+
+import java.lang.module.ModuleDescriptor.Requires;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+
+/**
+ * Determines if methods in a given class can be intrinsified.
+ *
+ * Only classes loaded from the module defining the compiler configuration or any of its transitive
+ * dependencies can be intrinsified.
+ *
+ * This version of the class must be used on JDK 9 or later.
+ */
+public final class IntrinsificationPredicate {
+ /**
+ * Set of modules composed of the module defining the compiler configuration and its transitive
+ * dependencies.
+ */
+ private final EconomicSet<Module> trustedModules;
+
+ IntrinsificationPredicate(CompilerConfiguration compilerConfiguration) {
+ trustedModules = EconomicSet.create();
+ Module compilerConfigurationModule = compilerConfiguration.getClass().getModule();
+ if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
+ throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
+ compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
+ }
+ trustedModules.add(compilerConfigurationModule);
+ for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
+ for (Module module : compilerConfigurationModule.getLayer().modules()) {
+ if (module.getName().equals(require.name())) {
+ trustedModules.add(module);
+ }
+ }
+ }
+ }
+
+ public boolean apply(Class<?> declaringClass) {
+ Module module = declaringClass.getModule();
+ return trustedModules.contains(module);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,7 +38,7 @@
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
@NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {Memory})
public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable, MemoryCheckpoint.Single {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java Thu Apr 26 17:59:02 2018 +0200
@@ -43,7 +43,7 @@
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
import jdk.vm.ci.meta.Constant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.InputType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java Thu Apr 26 17:59:02 2018 +0200
@@ -43,7 +43,7 @@
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint;
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,15 +25,12 @@
import static jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
-import jdk.vm.ci.meta.DeoptimizationAction;
-import jdk.vm.ci.meta.DeoptimizationReason;
-import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.JavaKind;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.CounterKey;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
@@ -74,6 +71,10 @@
import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.runtime.JVMCICompiler;
public class OnStackReplacementPhase extends Phase {
@@ -97,6 +98,7 @@
}
@Override
+ @SuppressWarnings("try")
protected void run(StructuredGraph graph) {
DebugContext debug = graph.getDebug();
if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) {
@@ -158,64 +160,67 @@
debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result");
} while (true);
+ StartNode start = graph.start();
FrameState osrState = osr.stateAfter();
- osr.setStateAfter(null);
- OSRStartNode osrStart = graph.add(new OSRStartNode());
- StartNode start = graph.start();
- FixedNode next = osr.next();
- osr.setNext(null);
- osrStart.setNext(next);
- graph.setStart(osrStart);
- osrStart.setStateAfter(osrState);
+ OSRStartNode osrStart;
+ try (DebugCloseable context = osr.withNodeSourcePosition()) {
+ osr.setStateAfter(null);
+ osrStart = graph.add(new OSRStartNode());
+ FixedNode next = osr.next();
+ osr.setNext(null);
+ osrStart.setNext(next);
+ graph.setStart(osrStart);
+ osrStart.setStateAfter(osrState);
+
+ debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start");
+ final int localsSize = osrState.localsSize();
+ final int locksSize = osrState.locksSize();
- debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start");
- final int localsSize = osrState.localsSize();
- final int locksSize = osrState.locksSize();
+ for (int i = 0; i < localsSize + locksSize; i++) {
+ ValueNode value = null;
+ if (i >= localsSize) {
+ value = osrState.lockAt(i - localsSize);
+ } else {
+ value = osrState.localAt(i);
+ }
+ if (value instanceof EntryProxyNode) {
+ EntryProxyNode proxy = (EntryProxyNode) value;
+ /*
+ * We need to drop the stamp since the types we see during OSR may be too
+ * precise (if a branch was not parsed for example). In cases when this is
+ * possible, we insert a guard and narrow the OSRLocal stamp at its usages.
+ */
+ Stamp narrowedStamp = proxy.value().stamp(NodeView.DEFAULT);
+ Stamp unrestrictedStamp = proxy.stamp(NodeView.DEFAULT).unrestricted();
+ ValueNode osrLocal;
+ if (i >= localsSize) {
+ osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, unrestrictedStamp));
+ } else {
+ osrLocal = graph.addOrUnique(new OSRLocalNode(i, unrestrictedStamp));
+ }
+ // Speculate on the OSRLocal stamps that could be more precise.
+ OSRLocalSpeculationReason reason = new OSRLocalSpeculationReason(osrState.bci, narrowedStamp, i);
+ if (graph.getSpeculationLog().maySpeculate(reason) && osrLocal instanceof OSRLocalNode && value.getStackKind().equals(JavaKind.Object) && !narrowedStamp.isUnrestricted()) {
+ // Add guard.
+ LogicNode check = graph.addOrUniqueWithInputs(InstanceOfNode.createHelper((ObjectStamp) narrowedStamp, osrLocal, null, null));
+ JavaConstant constant = graph.getSpeculationLog().speculate(reason);
+ FixedGuardNode guard = graph.add(new FixedGuardNode(check, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, constant, false));
+ graph.addAfterFixed(osrStart, guard);
- for (int i = 0; i < localsSize + locksSize; i++) {
- ValueNode value = null;
- if (i >= localsSize) {
- value = osrState.lockAt(i - localsSize);
- } else {
- value = osrState.localAt(i);
+ // Replace with a more specific type at usages.
+ // We know that we are at the root,
+ // so we need to replace the proxy in the state.
+ proxy.replaceAtMatchingUsages(osrLocal, n -> n == osrState);
+ osrLocal = graph.addOrUnique(new PiNode(osrLocal, narrowedStamp, guard));
+ }
+ proxy.replaceAndDelete(osrLocal);
+ } else {
+ assert value == null || value instanceof OSRLocalNode;
+ }
}
- if (value instanceof EntryProxyNode) {
- EntryProxyNode proxy = (EntryProxyNode) value;
- /*
- * We need to drop the stamp since the types we see during OSR may be too precise
- * (if a branch was not parsed for example). In cases when this is possible, we
- * insert a guard and narrow the OSRLocal stamp at its usages.
- */
- Stamp narrowedStamp = proxy.value().stamp(NodeView.DEFAULT);
- Stamp unrestrictedStamp = proxy.stamp(NodeView.DEFAULT).unrestricted();
- ValueNode osrLocal;
- if (i >= localsSize) {
- osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, unrestrictedStamp));
- } else {
- osrLocal = graph.addOrUnique(new OSRLocalNode(i, unrestrictedStamp));
- }
- // Speculate on the OSRLocal stamps that could be more precise.
- OSRLocalSpeculationReason reason = new OSRLocalSpeculationReason(osrState.bci, narrowedStamp, i);
- if (graph.getSpeculationLog().maySpeculate(reason) && osrLocal instanceof OSRLocalNode && value.getStackKind().equals(JavaKind.Object) && !narrowedStamp.isUnrestricted()) {
- // Add guard.
- LogicNode check = graph.addOrUniqueWithInputs(InstanceOfNode.createHelper((ObjectStamp) narrowedStamp, osrLocal, null, null));
- JavaConstant constant = graph.getSpeculationLog().speculate(reason);
- FixedGuardNode guard = graph.add(new FixedGuardNode(check, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, constant, false));
- graph.addAfterFixed(osrStart, guard);
- // Replace with a more specific type at usages.
- // We know that we are at the root,
- // so we need to replace the proxy in the state.
- proxy.replaceAtMatchingUsages(osrLocal, n -> n == osrState);
- osrLocal = graph.addOrUnique(new PiNode(osrLocal, narrowedStamp, guard));
- }
- proxy.replaceAndDelete(osrLocal);
- } else {
- assert value == null || value instanceof OSRLocalNode;
- }
+ osr.replaceAtUsages(InputType.Guard, osrStart);
}
-
- osr.replaceAtUsages(InputType.Guard, osrStart);
debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
GraphUtil.killCFG(start);
debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result");
@@ -223,21 +228,24 @@
if (currentOSRWithLocks) {
OsrWithLocksCount.increment(debug);
- for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) {
- MonitorIdNode id = osrState.monitorIdAt(i);
- ValueNode lockedObject = osrState.lockAt(i);
- OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id));
- for (Node usage : id.usages()) {
- if (usage instanceof AccessMonitorNode) {
- AccessMonitorNode access = (AccessMonitorNode) usage;
- access.setObject(lockedObject);
+ try (DebugCloseable context = osrStart.withNodeSourcePosition()) {
+ for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) {
+ MonitorIdNode id = osrState.monitorIdAt(i);
+ ValueNode lockedObject = osrState.lockAt(i);
+ OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id));
+ for (Node usage : id.usages()) {
+ if (usage instanceof AccessMonitorNode) {
+ AccessMonitorNode access = (AccessMonitorNode) usage;
+ access.setObject(lockedObject);
+ }
}
+ FixedNode oldNext = osrStart.next();
+ oldNext.replaceAtPredecessor(null);
+ osrMonitorEnter.setNext(oldNext);
+ osrStart.setNext(osrMonitorEnter);
}
- FixedNode oldNext = osrStart.next();
- oldNext.replaceAtPredecessor(null);
- osrMonitorEnter.setNext(oldNext);
- osrStart.setNext(osrMonitorEnter);
}
+
debug.dump(DebugContext.DETAILED_LEVEL, graph, "After inserting OSR monitor enters");
/*
* Ensure balanced monitorenter - monitorexit
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot.phases;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -53,22 +54,25 @@
this.config = config;
}
+ @SuppressWarnings("try")
@Override
protected void run(StructuredGraph graph) {
for (Node n : graph.getNodes()) {
- if (n instanceof ReadNode) {
- addReadNodeBarriers((ReadNode) n, graph);
- } else if (n instanceof WriteNode) {
- addWriteNodeBarriers((WriteNode) n, graph);
- } else if (n instanceof LoweredAtomicReadAndWriteNode) {
- LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n;
- addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph);
- } else if (n instanceof AbstractCompareAndSwapNode) {
- addCASBarriers((AbstractCompareAndSwapNode) n, graph);
- } else if (n instanceof ArrayRangeWrite) {
- ArrayRangeWrite node = (ArrayRangeWrite) n;
- if (node.writesObjectArray()) {
- addArrayRangeBarriers(node, graph);
+ try (DebugCloseable scope = n.graph().withNodeSourcePosition(n)) {
+ if (n instanceof ReadNode) {
+ addReadNodeBarriers((ReadNode) n, graph);
+ } else if (n instanceof WriteNode) {
+ addWriteNodeBarriers((WriteNode) n, graph);
+ } else if (n instanceof LoweredAtomicReadAndWriteNode) {
+ LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n;
+ addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph);
+ } else if (n instanceof AbstractCompareAndSwapNode) {
+ addCASBarriers((AbstractCompareAndSwapNode) n, graph);
+ } else if (n instanceof ArrayRangeWrite) {
+ ArrayRangeWrite node = (ArrayRangeWrite) n;
+ if (node.writesObjectArray()) {
+ addArrayRangeBarriers(node, graph);
+ }
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,6 +27,7 @@
import java.util.Map;
+import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.spi.Replacements;
import org.graalvm.compiler.options.Option;
@@ -36,6 +37,7 @@
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
+import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy;
import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
@@ -61,13 +63,14 @@
}
@Override
- public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+ public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+ final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions());
final InlineInfo info = invocation.callee();
for (int i = 0; i < info.numberOfMethods(); ++i) {
HotSpotResolvedObjectType t = (HotSpotResolvedObjectType) info.methodAt(i).getDeclaringClass();
if (t.getFingerprint() == 0) {
- return false;
+ return InliningPolicy.Decision.NO;
}
}
@@ -77,17 +80,17 @@
OptionValues options = info.graph().getOptions();
if (InlineEverything.getValue(options)) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything");
}
if (isIntrinsic(replacements, info)) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "intrinsic");
}
if (info.shouldInline()) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "forced inlining");
}
double inliningBonus = getInliningBonus(info);
@@ -95,17 +98,18 @@
if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
}
double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus));
if (nodes <= maximumNodes) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
nodes, maximumNodes);
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
+ nodes, maximumNodes);
}
InliningUtil.traceNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
- return false;
+ return InliningPolicy.Decision.NO.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ResolvedJavaType;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
import java.util.HashSet;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -41,9 +41,9 @@
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32CSubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32CSubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,9 +38,9 @@
import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -40,9 +40,9 @@
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -48,7 +48,7 @@
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ConstantReflectionProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java Thu Apr 26 17:59:02 2018 +0200
@@ -47,7 +47,7 @@
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Thu Apr 26 17:59:02 2018 +0200
@@ -59,8 +59,8 @@
import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
import org.graalvm.compiler.replacements.nodes.WriteRegisterNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java Thu Apr 26 17:59:02 2018 +0200
@@ -51,7 +51,7 @@
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Thu Apr 26 17:59:02 2018 +0200
@@ -120,10 +120,10 @@
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Thu Apr 26 17:59:02 2018 +0200
@@ -117,8 +117,8 @@
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.MemoryBarriers;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectSubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectSubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,11 @@
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
+import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
+import org.graalvm.compiler.graph.Node.NodeIntrinsic;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
// JaCoCo Exclude
@@ -37,4 +42,21 @@
public static int hashCode(final Object thisObj) {
return IdentityHashCodeNode.identityHashCode(thisObj);
}
+
+ @MethodSubstitution(isStatic = false)
+ public static void notify(final Object thisObj) {
+ if (!fastNotifyStub(HotSpotHostForeignCallsProvider.NOTIFY, thisObj)) {
+ notify(thisObj);
+ }
+ }
+
+ @MethodSubstitution(isStatic = false)
+ public static void notifyAll(final Object thisObj) {
+ if (!fastNotifyStub(HotSpotHostForeignCallsProvider.NOTIFY_ALL, thisObj)) {
+ notifyAll(thisObj);
+ }
+ }
+
+ @NodeIntrinsic(ForeignCallNode.class)
+ public static native boolean fastNotifyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object o);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
package org.graalvm.compiler.hotspot.replacements;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
@@ -33,8 +33,8 @@
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
package org.graalvm.compiler.hotspot.replacements;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
@@ -33,8 +33,8 @@
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
package org.graalvm.compiler.hotspot.replacements;
import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
@@ -33,8 +33,8 @@
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.extended.RawLoadNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,7 @@
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.compiler.replacements.nodes.CStringConstant;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.osThreadInterruptedOffset;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.osThreadOffset;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.threadObjectOffset;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.api.replacements.ClassSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java Thu Apr 26 17:59:02 2018 +0200
@@ -87,10 +87,10 @@
import org.graalvm.compiler.replacements.Snippets;
import org.graalvm.compiler.replacements.nodes.DirectStoreNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordFactory;
+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;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -58,7 +58,7 @@
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.hotspot.replacements.arraycopy;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
@@ -31,7 +31,7 @@
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,7 @@
import java.lang.reflect.Method;
import java.util.EnumMap;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.Snippet;
@@ -77,8 +77,8 @@
import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.DeoptimizationAction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -52,7 +52,7 @@
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.REEXECUTABLE;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java Thu Apr 26 17:59:02 2018 +0200
@@ -51,7 +51,7 @@
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,11 +34,9 @@
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
-import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.JavaMethodContext;
-import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
@@ -57,7 +55,7 @@
import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
import jdk.vm.ci.hotspot.HotSpotSignature;
@@ -232,33 +230,30 @@
WordTypes wordTypes = providers.getWordTypes();
Class<?>[] args = linkage.getDescriptor().getArgumentTypes();
boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn());
- StructuredGraph graph = new StructuredGraph.Builder(options, debug).name(toString()).compilationId(compilationId).build();
- graph.disableUnsafeAccessTracking();
- graph.setTrackNodeSourcePosition();
+
try {
ResolvedJavaMethod thisMethod = providers.getMetaAccess().lookupJavaMethod(ForeignCallStub.class.getDeclaredMethod("getGraph", DebugContext.class, CompilationIdentifier.class));
- try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(thisMethod))) {
- GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins());
- ParameterNode[] params = createParameters(kit, args);
- ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
- ValueNode result = createTargetCall(kit, params, thread);
- kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
- if (isObjectResult) {
- InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
- result = kit.createInvoke(StubUtil.class, "verifyObject", object);
- }
- kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
- debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
+ GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString());
+ StructuredGraph graph = kit.getGraph();
+ ParameterNode[] params = createParameters(kit, args);
+ ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
+ ValueNode result = createTargetCall(kit, params, thread);
+ kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
+ if (isObjectResult) {
+ InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
+ result = kit.createInvoke(StubUtil.class, "verifyObject", object);
+ }
+ kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
+ debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
- kit.inlineInvokes();
- new RemoveValueProxyPhase().apply(graph);
+ kit.inlineInvokes("Foreign call stub.", "Backend");
+ new RemoveValueProxyPhase().apply(graph);
- debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation");
- }
+ debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation");
+ return graph;
} catch (Exception e) {
throw GraalError.shouldNotReachHere(e);
}
- return graph;
}
private ParameterNode[] createParameters(GraphKit kit, Class<?>[] args) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java Thu Apr 26 17:59:02 2018 +0200
@@ -59,7 +59,7 @@
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java Thu Apr 26 17:59:02 2018 +0200
@@ -81,7 +81,7 @@
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java Thu Apr 26 17:59:02 2018 +0200
@@ -48,9 +48,10 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.TriState;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugContext.Description;
@@ -137,7 +138,7 @@
*/
public Stub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
this.linkage = linkage;
- this.options = options;
+ this.options = new OptionValues(options, GraalOptions.TraceInlining, GraalOptions.TraceInliningForStubsAndSnippets.getValue(options));
this.providers = providers;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java Thu Apr 26 17:59:02 2018 +0200
@@ -50,8 +50,8 @@
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.replacements.Log;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.DeoptimizationAction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java Thu Apr 26 17:59:02 2018 +0200
@@ -47,7 +47,7 @@
import org.graalvm.compiler.nodes.UnwindNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.Pointer;
import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,8 +29,8 @@
import org.graalvm.compiler.word.Word.Opcode;
import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
/**
* Marker type for a metaspace pointer to a type.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,11 +29,11 @@
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.Word.Opcode;
import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
/**
* Marker type for a metaspace pointer.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE;
import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.TO_METHOD_POINTER;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.Pointer;
/**
* Marker type for a metaspace pointer to a method.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,6 +38,7 @@
import static org.graalvm.compiler.bytecode.Bytecodes.FASTORE;
import static org.graalvm.compiler.bytecode.Bytecodes.FRETURN;
import static org.graalvm.compiler.bytecode.Bytecodes.GETFIELD;
+import static org.graalvm.compiler.bytecode.Bytecodes.GETSTATIC;
import static org.graalvm.compiler.bytecode.Bytecodes.GOTO;
import static org.graalvm.compiler.bytecode.Bytecodes.GOTO_W;
import static org.graalvm.compiler.bytecode.Bytecodes.IALOAD;
@@ -71,6 +72,7 @@
import static org.graalvm.compiler.bytecode.Bytecodes.LOOKUPSWITCH;
import static org.graalvm.compiler.bytecode.Bytecodes.LRETURN;
import static org.graalvm.compiler.bytecode.Bytecodes.PUTFIELD;
+import static org.graalvm.compiler.bytecode.Bytecodes.PUTSTATIC;
import static org.graalvm.compiler.bytecode.Bytecodes.RET;
import static org.graalvm.compiler.bytecode.Bytecodes.RETURN;
import static org.graalvm.compiler.bytecode.Bytecodes.SALOAD;
@@ -81,13 +83,12 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
import org.graalvm.compiler.bytecode.BytecodeStream;
@@ -142,20 +143,20 @@
public static class BciBlock implements Cloneable {
- protected int id;
- public int startBci;
- public int endBci;
- public boolean isExceptionEntry;
- public boolean isLoopHeader;
- public int loopId;
- public int loopEnd;
- protected List<BciBlock> successors;
+ int id;
+ final int startBci;
+ int endBci;
+ private boolean isExceptionEntry;
+ private boolean isLoopHeader;
+ int loopId;
+ int loopEnd;
+ List<BciBlock> successors;
private int predecessorCount;
private boolean visited;
private boolean active;
- public long loops;
- public JSRData jsrData;
+ long loops;
+ JSRData jsrData;
public static class JSRData implements Cloneable {
public EconomicMap<JsrScope, BciBlock> jsrAlternatives;
@@ -174,8 +175,21 @@
}
}
- public BciBlock() {
- this.successors = new ArrayList<>(4);
+ BciBlock(int startBci) {
+ this.startBci = startBci;
+ this.successors = new ArrayList<>();
+ }
+
+ public int getStartBci() {
+ return startBci;
+ }
+
+ public int getEndBci() {
+ return endBci;
+ }
+
+ public long getLoops() {
+ return loops;
}
public BciBlock exceptionDispatchBlock() {
@@ -216,14 +230,16 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder("B").append(getId());
- sb.append('[').append(startBci).append("->").append(endBci);
- if (isLoopHeader || isExceptionEntry) {
+ sb.append('[').append(startBci).append("..").append(endBci);
+ if (isLoopHeader || isExceptionEntry || this instanceof ExceptionDispatchBlock) {
sb.append(' ');
if (isLoopHeader) {
sb.append('L');
}
if (isExceptionEntry) {
sb.append('!');
+ } else if (this instanceof ExceptionDispatchBlock) {
+ sb.append("<!>");
}
}
sb.append(']');
@@ -412,11 +428,40 @@
}
successors.clear();
}
+
+ public boolean isExceptionDispatch() {
+ return false;
+ }
}
public static class ExceptionDispatchBlock extends BciBlock {
- public ExceptionHandler handler;
- public int deoptBci;
+ public final ExceptionHandler handler;
+ public final int deoptBci;
+
+ /**
+ * Constructor for a normal dispatcher.
+ */
+ ExceptionDispatchBlock(ExceptionHandler handler, int deoptBci) {
+ super(handler.getHandlerBCI());
+ this.endBci = startBci;
+ this.deoptBci = deoptBci;
+ this.handler = handler;
+ }
+
+ /**
+ * Constructor for the method unwind dispatcher.
+ */
+ ExceptionDispatchBlock(int deoptBci) {
+ super(deoptBci);
+ this.endBci = deoptBci;
+ this.deoptBci = deoptBci;
+ this.handler = null;
+ }
+
+ @Override
+ public boolean isExceptionDispatch() {
+ return true;
+ }
}
/**
@@ -480,7 +525,6 @@
private boolean verify() {
for (BciBlock block : blocks) {
assert blocks[block.getId()] == block;
-
for (int i = 0; i < block.getSuccessorCount(); i++) {
BciBlock sux = block.getSuccessor(i);
if (sux instanceof ExceptionDispatchBlock) {
@@ -623,6 +667,8 @@
case CALOAD:
case SALOAD:
case ARRAYLENGTH:
+ case PUTSTATIC:
+ case GETSTATIC:
case PUTFIELD:
case GETFIELD: {
ExceptionDispatchBlock handler = handleExceptions(blockMap, bci);
@@ -640,18 +686,16 @@
private BciBlock makeBlock(BciBlock[] blockMap, int startBci) {
BciBlock oldBlock = blockMap[startBci];
if (oldBlock == null) {
- BciBlock newBlock = new BciBlock();
+ BciBlock newBlock = new BciBlock(startBci);
blocksNotYetAssignedId++;
- newBlock.startBci = startBci;
blockMap[startBci] = newBlock;
return newBlock;
} else if (oldBlock.startBci != startBci) {
// Backward branch into the middle of an already processed block.
// Add the correct fall-through successor.
- BciBlock newBlock = new BciBlock();
+ BciBlock newBlock = new BciBlock(startBci);
blocksNotYetAssignedId++;
- newBlock.startBci = startBci;
newBlock.endBci = oldBlock.endBci;
for (BciBlock oldSuccessor : oldBlock.getSuccessors()) {
newBlock.addSuccessor(oldSuccessor);
@@ -747,6 +791,7 @@
private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) {
ExceptionDispatchBlock lastHandler = null;
+ int dispatchBlocks = 0;
for (int i = exceptionHandlers.length - 1; i >= 0; i--) {
ExceptionHandler h = exceptionHandlers[i];
@@ -754,17 +799,14 @@
if (h.isCatchAll()) {
// Discard all information about succeeding exception handlers, since they can
// never be reached.
+ dispatchBlocks = 0;
lastHandler = null;
}
// We do not reuse exception dispatch blocks, because nested exception handlers
// might have problems reasoning about the correct frame state.
- ExceptionDispatchBlock curHandler = new ExceptionDispatchBlock();
- blocksNotYetAssignedId++;
- curHandler.startBci = -1;
- curHandler.endBci = -1;
- curHandler.deoptBci = bci;
- curHandler.handler = h;
+ ExceptionDispatchBlock curHandler = new ExceptionDispatchBlock(h, bci);
+ dispatchBlocks++;
curHandler.addSuccessor(blockMap[h.getHandlerBCI()]);
if (lastHandler != null) {
curHandler.addSuccessor(lastHandler);
@@ -772,6 +814,7 @@
lastHandler = curHandler;
}
}
+ blocksNotYetAssignedId += dispatchBlocks;
return lastHandler;
}
@@ -827,10 +870,8 @@
assert next == newBlocks.length - 1;
// Add unwind block.
- ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock();
- unwindBlock.startBci = -1;
- unwindBlock.endBci = -1;
- unwindBlock.deoptBci = code.getMethod().isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI;
+ int deoptBci = code.getMethod().isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI;
+ ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(deoptBci);
unwindBlock.setId(newBlocks.length - 1);
newBlocks[newBlocks.length - 1] = unwindBlock;
@@ -858,42 +899,54 @@
public void log(BciBlock[] blockMap, String name) {
if (debug.isLogEnabled()) {
- String n = System.lineSeparator();
- StringBuilder sb = new StringBuilder(debug.getCurrentScopeName()).append("BlockMap ").append(name).append(" :");
- sb.append(n);
- Iterable<BciBlock> it;
- if (blocks == null) {
- it = new HashSet<>(Arrays.asList(blockMap));
- } else {
- it = Arrays.asList(blocks);
+ debug.log("%sBlockMap %s: %n%s", debug.getCurrentScopeName(), name, toString(blockMap, loopHeaders));
+ }
+ }
+
+ public static String toString(BciBlock[] blockMap, BciBlock[] loopHeadersMap) {
+ StringBuilder sb = new StringBuilder();
+ for (BciBlock b : blockMap) {
+ if (b == null) {
+ continue;
+ }
+ sb.append("B").append(b.getId()).append("[").append(b.startBci).append("..").append(b.endBci).append("]");
+ if (b.isLoopHeader) {
+ sb.append(" LoopHeader");
}
- for (BciBlock b : it) {
- if (b == null) {
- continue;
- }
- sb.append("B").append(b.getId()).append(" (").append(b.startBci).append(" -> ").append(b.endBci).append(")");
- if (b.isLoopHeader) {
- sb.append(" LoopHeader");
+ if (b.isExceptionEntry) {
+ sb.append(" ExceptionEntry");
+ }
+ if (b instanceof ExceptionDispatchBlock) {
+ sb.append(" ExceptionDispatch");
+ }
+ if (!b.successors.isEmpty()) {
+ sb.append(" Successors=[");
+ for (BciBlock s : b.getSuccessors()) {
+ if (sb.charAt(sb.length() - 1) != '[') {
+ sb.append(", ");
+ }
+ sb.append("B").append(s.getId());
}
- if (b.isExceptionEntry) {
- sb.append(" ExceptionEntry");
- }
- sb.append(n).append(" Sux : ");
- for (BciBlock s : b.getSuccessors()) {
- sb.append("B").append(s.getId()).append(" (").append(s.startBci).append(" -> ").append(s.endBci).append(")");
- if (s.isExceptionEntry) {
- sb.append("!");
+ sb.append("]");
+ }
+ if (b.loops != 0L) {
+ sb.append(" Loops=[");
+ for (int pos : b.loopIdIterable()) {
+ if (sb.charAt(sb.length() - 1) == '[') {
+ sb.append(", ");
}
- sb.append(" ");
+ sb.append("B").append(loopHeadersMap[pos].getId());
}
- sb.append(n).append(" Loop : ");
- for (int pos : b.loopIdIterable()) {
- sb.append("B").append(loopHeaders[pos].getId()).append(" ");
- }
- sb.append(n);
+ sb.append("]");
}
- debug.log("%s", sb);
+ sb.append(System.lineSeparator());
}
+ return sb.toString();
+ }
+
+ @Override
+ public String toString() {
+ return toString(blocks, loopHeaders);
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Apr 26 17:59:02 2018 +0200
@@ -265,8 +265,8 @@
import java.util.Formatter;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
@@ -297,8 +297,10 @@
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.Indent;
+import org.graalvm.compiler.debug.MethodFilter;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.graph.Graph.Mark;
import org.graalvm.compiler.graph.Node;
@@ -325,6 +327,7 @@
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.FullInfopointNode;
import org.graalvm.compiler.nodes.IfNode;
+import org.graalvm.compiler.nodes.InliningLog;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.InvokeNode;
import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
@@ -414,7 +417,7 @@
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;
import org.graalvm.compiler.phases.util.ValueMergeUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodeFrame;
@@ -454,11 +457,17 @@
/**
* The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
- * to trace the frame state before each bytecode instruction as it is parsed.
+ * to emit the frame state for each traced bytecode instruction.
*/
public static final int TRACELEVEL_STATE = 2;
/**
+ * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
+ * to emit the block map for each traced method.
+ */
+ public static final int TRACELEVEL_BLOCKMAP = 3;
+
+ /**
* Meters the number of actual bytecodes parsed.
*/
public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed");
@@ -681,6 +690,7 @@
private ValueNode originalReceiver;
private final boolean eagerInitializing;
private final boolean uninitializedIsError;
+ private final int traceLevel;
protected BytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance, StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method,
int entryBCI, IntrinsicContext intrinsicContext) {
@@ -714,12 +724,6 @@
assert code.getCode() != null : "method must contain bytecodes: " + method;
- if (TraceBytecodeParserLevel.getValue(options) != 0) {
- if (!Assertions.assertionsEnabled()) {
- throw new IllegalArgumentException("A non-zero " + TraceBytecodeParserLevel.getName() + " value requires assertions to be enabled");
- }
- }
-
if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
lnt = code.getLineNumberTable();
previousLineNumber = -1;
@@ -729,6 +733,24 @@
if (graphBuilderConfig.trackNodeSourcePosition() || (parent != null && parent.graph.trackNodeSourcePosition())) {
graph.setTrackNodeSourcePosition();
}
+
+ int level = TraceBytecodeParserLevel.getValue(options);
+ this.traceLevel = level != 0 ? refineTraceLevel(level) : 0;
+ }
+
+ private int refineTraceLevel(int level) {
+ ResolvedJavaMethod tmethod = graph.method();
+ if (tmethod == null) {
+ tmethod = method;
+ }
+ String filterValue = DebugOptions.MethodFilter.getValue(options);
+ if (filterValue != null) {
+ MethodFilter[] filters = MethodFilter.parse(filterValue);
+ if (!MethodFilter.matches(filters, tmethod)) {
+ return 0;
+ }
+ }
+ return level;
}
protected GraphBuilderPhase.Instance getGraphBuilderInstance() {
@@ -847,7 +869,7 @@
currentBlock = blockMap.getStartBlock();
setEntryState(startBlock, frameState);
- if (startBlock.isLoopHeader) {
+ if (startBlock.isLoopHeader()) {
appendGoto(startBlock);
} else {
setFirstInstruction(startBlock, lastInstr);
@@ -1676,6 +1698,7 @@
targetMethod = originalMethod;
}
Invoke invoke = createNonInlinedInvoke(edgeAction, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
+ graph.getInliningLog().addDecision(invoke, false, "GraphBuilderPhase", null, null, "bytecode parser did not replace invoke");
if (partialIntrinsicExit) {
// This invoke must never be later inlined as it might select the intrinsic graph.
// Until there is a mechanism to guarantee that any late inlining will not select
@@ -2172,60 +2195,80 @@
}
private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) {
- IntrinsicContext intrinsic = this.intrinsicContext;
-
- if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() &&
- targetMethod.equals(inlinedMethod) &&
- (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 &&
- tryFastInlineAccessor(args, targetMethod)) {
- return true;
- }
-
- if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
- if (intrinsic.isCompilationRoot()) {
- // A root compiled intrinsic needs to deoptimize
- // if the slow path is taken. During frame state
- // assignment, the deopt node will get its stateBefore
- // from the start node of the intrinsic
- append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
- printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
+ try (InliningLog.RootScope scope = graph.getInliningLog().openRootScope(targetMethod, bci())) {
+ IntrinsicContext intrinsic = this.intrinsicContext;
+
+ if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() &&
+ targetMethod.equals(inlinedMethod) &&
+ (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 &&
+ tryFastInlineAccessor(args, targetMethod)) {
return true;
- } else {
- if (intrinsic.getOriginalMethod().isNative()) {
- printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
- return false;
- }
- if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
- // Otherwise inline the original method. Any frame state created
- // during the inlining will exclude frame(s) in the
- // intrinsic method (see FrameStateBuilder.create(int bci)).
- notifyBeforeInline(inlinedMethod);
- printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
- parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
- notifyAfterInline(inlinedMethod);
+ }
+
+ if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
+ if (intrinsic.isCompilationRoot()) {
+ // A root compiled intrinsic needs to deoptimize
+ // if the slow path is taken. During frame state
+ // assignment, the deopt node will get its stateBefore
+ // from the start node of the intrinsic
+ append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
+ printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
+ if (scope != null) {
+ graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "compilation root");
+ }
return true;
} else {
- printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
+ if (intrinsic.getOriginalMethod().isNative()) {
+ printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
+ if (scope != null) {
+ graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method");
+ }
+ return false;
+ }
+ if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
+ // Otherwise inline the original method. Any frame state created
+ // during the inlining will exclude frame(s) in the
+ // intrinsic method (see FrameStateBuilder.create(int bci)).
+ notifyBeforeInline(inlinedMethod);
+ printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
+ if (scope != null) {
+ graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "partial intrinsic exit");
+ }
+ parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
+ notifyAfterInline(inlinedMethod);
+ return true;
+ } else {
+ printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
+ if (scope != null) {
+ graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "partial intrinsic exit");
+ }
+ return false;
+ }
+ }
+ } else {
+ boolean isIntrinsic = intrinsicBytecodeProvider != null;
+ if (intrinsic == null && isIntrinsic) {
+ assert !inlinedMethod.equals(targetMethod);
+ intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING);
+ }
+ if (inlinedMethod.hasBytecodes()) {
+ notifyBeforeInline(inlinedMethod);
+ printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)");
+ if (scope != null) {
+ graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "inline method");
+ }
+ parseAndInlineCallee(inlinedMethod, args, intrinsic);
+ notifyAfterInline(inlinedMethod);
+ } else {
+ printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)");
+ if (scope != null) {
+ graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "no bytecodes (abstract or native)");
+ }
return false;
}
}
- } else {
- boolean isIntrinsic = intrinsicBytecodeProvider != null;
- if (intrinsic == null && isIntrinsic) {
- assert !inlinedMethod.equals(targetMethod);
- intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING);
- }
- if (inlinedMethod.hasBytecodes()) {
- notifyBeforeInline(inlinedMethod);
- printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)");
- parseAndInlineCallee(inlinedMethod, args, intrinsic);
- notifyAfterInline(inlinedMethod);
- } else {
- printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)");
- return false;
- }
- }
- return true;
+ return true;
+ }
}
protected void notifyBeforeInline(ResolvedJavaMethod inlinedMethod) {
@@ -2700,7 +2743,7 @@
@SuppressWarnings("try")
private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
assert block != null && state != null;
- assert !block.isExceptionEntry || state.stackSize() == 1;
+ assert !block.isExceptionEntry() || state.stackSize() == 1;
try (DebugCloseable context = openNodeContext(state, block.startBci)) {
if (getFirstInstruction(block) == null) {
@@ -2710,7 +2753,7 @@
* again.
*/
FixedNode targetNode;
- if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
+ if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader() && (currentBlock.loops & ~block.loops) == 0) {
setFirstInstruction(block, lastInstr);
lastInstr = null;
} else {
@@ -2729,11 +2772,11 @@
// We already saw this block before, so we have to merge states.
if (!getEntryState(block).isCompatibleWith(state)) {
- throw bailout("stacks do not match; bytecodes would not verify");
+ throw bailout(String.format("stacks do not match on merge from %d into %s; bytecodes would not verify:%nexpect: %s%nactual: %s", bci(), block, getEntryState(block), state));
}
if (getFirstInstruction(block) instanceof LoopBeginNode) {
- assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
+ assert (block.isLoopHeader() && currentBlock.getId() >= block.getId()) : "must be backward branch";
/*
* Backward loop edge. We need to create a special LoopEndNode and merge with the
* loop begin node created before.
@@ -2820,7 +2863,7 @@
debug.log("Ignoring block %s", block);
return;
}
- try (Indent indent = debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) {
+ try (Indent indent = debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader())) {
lastInstr = firstInstruction;
frameState = getEntryState(block);
@@ -2949,11 +2992,11 @@
@SuppressWarnings("try")
protected void iterateBytecodesForBlock(BciBlock block) {
- if (block.isLoopHeader) {
+ if (block.isLoopHeader()) {
// Create the loop header block, which later will merge the backward branches of
// the loop.
controlFlowSplit = true;
- LoopBeginNode loopBegin = appendLoopBegin(this.lastInstr);
+ LoopBeginNode loopBegin = appendLoopBegin(this.lastInstr, block.startBci);
lastInstr = loopBegin;
// Create phi functions for all local variables and operand stack slots.
@@ -3007,8 +3050,9 @@
// read the opcode
int opcode = stream.currentBC();
- assert traceState();
- assert traceInstruction(bci, opcode, bci == block.startBci);
+ if (traceLevel != 0) {
+ traceInstruction(bci, opcode, bci == block.startBci);
+ }
if (parent == null && bci == entryBCI) {
if (block.getJsrScope() != JsrScope.EMPTY_SCOPE) {
throw new JsrNotSupportedBailout("OSR into a JSR scope is not supported");
@@ -3038,7 +3082,7 @@
lastInstr = finishInstruction(lastInstr, frameState);
if (bci < endBCI) {
if (bci > block.endBci) {
- assert !block.getSuccessor(0).isExceptionEntry;
+ assert !block.getSuccessor(0).isExceptionEntry();
assert block.numNormalSuccessors() == 1;
// we fell through to the next block, add a goto and break
appendGoto(block.getSuccessor(0));
@@ -3097,16 +3141,19 @@
return parsingIntrinsic();
}
- private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext) {
- EndNode preLoopEnd = graph.add(new EndNode());
- LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
- if (disableLoopSafepoint()) {
- loopBegin.disableSafepoint();
- }
- fixedWithNext.setNext(preLoopEnd);
- // Add the single non-loop predecessor of the loop header.
- loopBegin.addForwardEnd(preLoopEnd);
- return loopBegin;
+ @SuppressWarnings("try")
+ private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext, int startBci) {
+ try (DebugCloseable context = openNodeContext(frameState, startBci)) {
+ EndNode preLoopEnd = graph.add(new EndNode());
+ LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
+ if (disableLoopSafepoint()) {
+ loopBegin.disableSafepoint();
+ }
+ fixedWithNext.setNext(preLoopEnd);
+ // Add the single non-loop predecessor of the loop header.
+ loopBegin.addForwardEnd(preLoopEnd);
+ return loopBegin;
+ }
}
/**
@@ -3126,13 +3173,6 @@
}
}
- private boolean traceState() {
- if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) {
- frameState.traceState();
- }
- return true;
- }
-
protected void genIf(ValueNode x, Condition cond, ValueNode y) {
assert x.getStackKind() == y.getStackKind();
assert currentBlock.getSuccessorCount() == 2;
@@ -3249,19 +3289,23 @@
}
if (isNeverExecutedCode(probability)) {
- append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
- if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
- profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
+ if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != trueBlock.startBci) {
+ append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
+ if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
+ profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
+ }
+ appendGoto(falseBlock);
+ return;
}
- appendGoto(falseBlock);
- return;
} else if (isNeverExecutedCode(1 - probability)) {
- append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
- if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
- profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
+ if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != falseBlock.startBci) {
+ append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
+ if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
+ profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
+ }
+ appendGoto(trueBlock);
+ return;
}
- appendGoto(trueBlock);
- return;
}
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
@@ -4677,15 +4721,25 @@
return frameState;
}
- protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
- if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) {
- traceInstructionHelper(bci, opcode, blockStart);
- }
- return true;
- }
-
- private void traceInstructionHelper(int bci, int opcode, boolean blockStart) {
+ private boolean firstTraceEmitted;
+
+ protected void traceInstruction(int bci, int opcode, boolean blockStart) {
+ String indent = new String(new char[getDepth() * 2]).replace('\0', ' ');
StringBuilder sb = new StringBuilder(40);
+ String nl = System.lineSeparator();
+ if (!firstTraceEmitted) {
+ sb.append(indent).append(method.format("Parsing %H.%n(%p)%r")).append(nl);
+ if (traceLevel >= TRACELEVEL_BLOCKMAP) {
+ sb.append(indent).append("Blocks:").append(nl);
+ String bm = blockMap.toString().replace(nl, nl + indent + " ");
+ sb.append(indent).append(" ").append(bm).append(nl);
+ }
+ firstTraceEmitted = true;
+ }
+ if (traceLevel >= TRACELEVEL_STATE) {
+ sb.append(indent).append(frameState).append(nl);
+ }
+ sb.append(indent);
sb.append(blockStart ? '+' : '|');
if (bci < 10) {
sb.append(" ");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,8 +35,10 @@
public class BytecodeParserOptions {
// @formatter:off
@Option(help = "The trace level for the bytecode parser. A value of 1 enables instruction tracing " +
- "and any greater value emits a frame state trace just prior to an instruction trace. " +
- "This option requires assertions to be enabled.", type = OptionType.Debug)
+ "and any greater value emits a frame state trace just prior to each instruction trace." +
+ "Instruction tracing output from multiple compiler threads will be interleaved so " +
+ "use of this option make most sense for single threaded compilation. " +
+ "The MethodFilter option can be used to refine tracing to selected methods.", type = OptionType.Debug)
public static final OptionKey<Integer> TraceBytecodeParserLevel = new OptionKey<>(0);
@Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.ControlSplitNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -46,7 +46,6 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.java.BciBlockMapping.BciBlock;
import org.graalvm.compiler.nodeinfo.Verbosity;
@@ -982,16 +981,4 @@
}
sideEffects.add(sideEffect);
}
-
- public void traceState() {
- TTY.println("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod());
- for (int i = 0; i < localsSize(); ++i) {
- ValueNode value = locals[i];
- TTY.println("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
- }
- for (int i = 0; i < stackSize(); ++i) {
- ValueNode value = stack[i];
- TTY.println("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
- }
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java Thu Apr 26 17:59:02 2018 +0200
@@ -220,7 +220,7 @@
protected abstract void storeOne(int blockID, int local);
private void computeLocalLiveness(BytecodeStream stream, BciBlock block) {
- if (block.startBci < 0 || block.endBci < 0) {
+ if (block.isExceptionDispatch()) {
return;
}
int blockID = block.getId();
--- /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/AArch64ArrayCompareToOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.lir.aarch64;
+
+import static jdk.vm.ci.aarch64.AArch64.zr;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.aarch64.AArch64Address;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
+import org.graalvm.compiler.core.common.LIRKind;
+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 jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
+import sun.misc.Unsafe;
+
+/**
+ * Emits code which compares two arrays lexicographically. If the CPU supports any vector
+ * instructions specialized code is emitted to leverage these instructions.
+ */
+@Opcode("ARRAY_COMPARE_TO")
+public final class AArch64ArrayCompareToOp extends AArch64LIRInstruction {
+ public static final LIRInstructionClass<AArch64ArrayCompareToOp> TYPE = LIRInstructionClass.create(AArch64ArrayCompareToOp.class);
+
+ private final JavaKind kind1;
+ private final JavaKind kind2;
+
+ private final int array1BaseOffset;
+ private final int array2BaseOffset;
+
+ @Def({REG}) protected Value resultValue;
+
+ @Alive({REG}) protected Value array1Value;
+ @Alive({REG}) protected Value array2Value;
+ @Use({REG}) protected Value length1Value;
+ @Use({REG}) protected Value length2Value;
+ @Temp({REG}) protected Value length1ValueTemp;
+ @Temp({REG}) protected Value length2ValueTemp;
+
+ @Temp({REG}) protected Value temp1;
+ @Temp({REG}) protected Value temp2;
+ @Temp({REG}) protected Value temp3;
+ @Temp({REG}) protected Value temp4;
+ @Temp({REG}) protected Value temp5;
+ @Temp({REG}) protected Value temp6;
+
+ public AArch64ArrayCompareToOp(LIRGeneratorTool tool, JavaKind kind1, JavaKind kind2, Value result, Value array1, Value array2, Value length1, Value length2) {
+ super(TYPE);
+ this.kind1 = kind1;
+ this.kind2 = kind2;
+
+ // Both offsets should be the same but better be safe than sorry.
+ Class<?> array1Class = Array.newInstance(kind1.toJavaClass(), 0).getClass();
+ Class<?> array2Class = Array.newInstance(kind2.toJavaClass(), 0).getClass();
+ this.array1BaseOffset = UNSAFE.arrayBaseOffset(array1Class);
+ this.array2BaseOffset = UNSAFE.arrayBaseOffset(array2Class);
+
+ this.resultValue = result;
+
+ this.array1Value = array1;
+ this.array2Value = array2;
+
+ /*
+ * The length values are inputs but are also killed like temporaries so need both Use and
+ * Temp annotations, which will only work with fixed registers.
+ */
+
+ this.length1Value = length1;
+ this.length2Value = length2;
+ this.length1ValueTemp = length1;
+ this.length2ValueTemp = length2;
+
+ // Allocate some temporaries.
+ 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.unknownReference(tool.target().arch.getWordKind()));
+ this.temp4 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+ this.temp5 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+ this.temp6 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+ }
+
+ private static final Unsafe UNSAFE = initUnsafe();
+
+ private static Unsafe initUnsafe() {
+ try {
+ return Unsafe.getUnsafe();
+ } catch (SecurityException se) {
+ try {
+ Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+ theUnsafe.setAccessible(true);
+ return (Unsafe) theUnsafe.get(Unsafe.class);
+ } catch (Exception e) {
+ throw new RuntimeException("exception while trying to get Unsafe", e);
+ }
+ }
+ }
+
+ @Override
+ protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
+
+ Register result = asRegister(resultValue);
+ Register length1 = asRegister(length1Value);
+ Register length2 = asRegister(length2Value);
+
+ Register array1 = asRegister(temp1);
+ Register array2 = asRegister(temp2);
+ Register length = asRegister(temp3);
+ Register temp = asRegister(temp4);
+ Register tailCount = asRegister(temp5);
+ Register vecCount = asRegister(temp6);
+
+ // Checkstyle: stop
+ final Label BREAK_LABEL = new Label();
+ final Label STRING_DIFFER_LABEL = new Label();
+ final Label LENGTH_DIFFER_LABEL = new Label();
+ final Label MAIN_LOOP_LABEL = new Label();
+ final Label COMPARE_SHORT_LABEL = new Label();
+ // Checkstyle: resume
+
+ // Checkstyle: stop
+ int CHAR_SIZE_BYTES = 1;
+ int VECTOR_SIZE_BYTES = 8;
+ int VECTOR_COUNT_BYTES = 8;
+ // Checkstyle: resume
+
+ // Byte is expanded to short if we compare strings with different encoding
+ if (kind1 != kind2 || kind1 == JavaKind.Char) {
+ CHAR_SIZE_BYTES = 2;
+ }
+
+ if (kind1 != kind2) {
+ VECTOR_COUNT_BYTES = 4;
+ }
+
+ // Load array base addresses.
+ masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(asRegister(array1Value), array1BaseOffset));
+ masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(asRegister(array2Value), array2BaseOffset));
+
+ // Calculate minimal length in chars for different kind case
+ // Conditions could be squashed but lets keep it readable
+ if (kind1 != kind2) {
+ masm.lshr(64, length2, length2, 1);
+ }
+
+ if (kind1 == kind2 && kind1 == JavaKind.Char) {
+ masm.lshr(64, length1, length1, 1);
+ masm.lshr(64, length2, length2, 1);
+ }
+
+ masm.cmp(64, length1, length2);
+ masm.cmov(64, length, length1, length2, ConditionFlag.LT);
+
+ // One of strings is empty
+ masm.cbz(64, length, LENGTH_DIFFER_LABEL);
+
+ // Go back to bytes if necessary
+ if (kind1 != kind2 || kind1 == JavaKind.Char) {
+ masm.shl(64, length, length, 1);
+ }
+
+ masm.mov(64, vecCount, zr);
+ masm.and(64, tailCount, length, VECTOR_SIZE_BYTES - 1); // tail count (in bytes)
+ masm.ands(64, length, length, ~(VECTOR_SIZE_BYTES - 1)); // vector count (in bytes)
+
+ // Length of string is less than VECTOR_SIZE, go to simple compare
+ masm.branchConditionally(ConditionFlag.EQ, COMPARE_SHORT_LABEL);
+
+ // MAIN_LOOP - read strings by 8 byte.
+ masm.bind(MAIN_LOOP_LABEL);
+ if (kind1 != kind2) {
+ // Load 32 bits ad unpack it to entire 64bit register
+ masm.ldr(32, result, AArch64Address.createRegisterOffsetAddress(array1, vecCount, false));
+ masm.ubfm(64, temp, result, 0, 7);
+ masm.lshr(64, result, result, 8);
+ masm.bfm(64, temp, result, 48, 7);
+ masm.lshr(64, result, result, 8);
+ masm.bfm(64, temp, result, 32, 7);
+ masm.lshr(64, result, result, 8);
+ masm.bfm(64, temp, result, 16, 7);
+ // Unpacked value placed in temp now
+
+ masm.shl(64, result, vecCount, 1);
+ masm.ldr(64, result, AArch64Address.createRegisterOffsetAddress(array2, result, false));
+ } else {
+ masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, vecCount, false));
+ masm.ldr(64, result, AArch64Address.createRegisterOffsetAddress(array2, vecCount, false));
+ }
+ masm.eor(64, result, temp, result);
+ masm.cbnz(64, result, STRING_DIFFER_LABEL);
+ masm.add(64, vecCount, vecCount, VECTOR_COUNT_BYTES);
+ masm.cmp(64, vecCount, length);
+ masm.branchConditionally(ConditionFlag.LT, MAIN_LOOP_LABEL);
+ // End of MAIN_LOOP
+
+ // Strings are equal and no TAIL go to END
+ masm.cbz(64, tailCount, LENGTH_DIFFER_LABEL);
+
+ // Compaire tail of long string ...
+ masm.lea(array1, AArch64Address.createRegisterOffsetAddress(array1, length, false));
+ masm.lea(array2, AArch64Address.createRegisterOffsetAddress(array2, length, false));
+
+ // ... or string less than vector length
+ masm.bind(COMPARE_SHORT_LABEL);
+ for (int i = 0; i < VECTOR_COUNT_BYTES; i += CHAR_SIZE_BYTES) {
+ if (kind1 != kind2) {
+ masm.ldr(8, temp, AArch64Address.createUnscaledImmediateAddress(array1, i / 2));
+ } else {
+ masm.ldr(8 * CHAR_SIZE_BYTES, temp, AArch64Address.createUnscaledImmediateAddress(array1, i));
+ }
+
+ masm.ldr(8 * CHAR_SIZE_BYTES, result, AArch64Address.createUnscaledImmediateAddress(array2, i));
+
+ if (kind1 != kind2 && kind1 == JavaKind.Char) {
+ // Weird swap of substraction order
+ masm.subs(64, result, result, temp);
+ } else {
+ masm.subs(64, result, temp, result);
+ }
+
+ masm.branchConditionally(ConditionFlag.NE, BREAK_LABEL);
+ masm.subs(64, tailCount, tailCount, CHAR_SIZE_BYTES);
+ masm.branchConditionally(ConditionFlag.EQ, LENGTH_DIFFER_LABEL);
+ }
+
+ // STRING_DIFFER extract exact value of a difference
+ masm.bind(STRING_DIFFER_LABEL);
+ masm.rbit(64, tailCount, result);
+ masm.clz(64, vecCount, tailCount);
+ masm.and(64, vecCount, vecCount, ~((8 * CHAR_SIZE_BYTES) - 1)); // Round to byte or short
+
+ masm.eor(64, result, temp, result);
+ masm.ashr(64, result, result, vecCount);
+ masm.ashr(64, temp, temp, vecCount);
+
+ masm.and(64, result, result, 0xFFFF >>> (16 - (8 * CHAR_SIZE_BYTES))); // 0xFF or 0xFFFF
+ masm.and(64, temp, temp, 0xFFFF >>> (16 - (8 * CHAR_SIZE_BYTES)));
+
+ masm.sub(64, result, temp, result);
+ masm.branchConditionally(ConditionFlag.AL, BREAK_LABEL);
+ // End of STRING_DIFFER
+
+ // Strings are equials up to length,
+ // return length difference in chars
+ masm.bind(LENGTH_DIFFER_LABEL);
+ if (kind1 != kind2 && kind1 == JavaKind.Char) {
+ // Weird swap of substraction order
+ masm.sub(64, result, length2, length1);
+ } else {
+ masm.sub(64, result, length1, length2);
+ }
+
+ // We are done
+ masm.bind(BREAK_LABEL);
+ }
+
+} // class
--- /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/AArch64AtomicMove.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.lir.aarch64;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.aarch64.AArch64.CPUFeature;
+import jdk.vm.ci.aarch64.AArch64.Flag;
+import jdk.vm.ci.aarch64.AArch64Kind;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
+
+public class AArch64AtomicMove {
+ /**
+ * Compare and swap instruction. Does the following atomically: <code>
+ * CAS(newVal, expected, address):
+ * oldVal = *address
+ * if oldVal == expected:
+ * *address = newVal
+ * return oldVal
+ * </code>
+ */
+ @Opcode("CAS")
+ public static class CompareAndSwapOp extends AArch64LIRInstruction {
+ public static final LIRInstructionClass<CompareAndSwapOp> TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
+
+ @Def protected AllocatableValue resultValue;
+ @Alive protected Value expectedValue;
+ @Alive protected AllocatableValue newValue;
+ @Alive protected AllocatableValue addressValue;
+ @Temp protected AllocatableValue scratchValue;
+
+ public CompareAndSwapOp(AllocatableValue result, Value expectedValue, AllocatableValue newValue, AllocatableValue addressValue, AllocatableValue scratch) {
+ super(TYPE);
+ this.resultValue = result;
+ this.expectedValue = expectedValue;
+ this.newValue = newValue;
+ this.addressValue = addressValue;
+ this.scratchValue = scratch;
+ }
+
+ @Override
+ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
+ AArch64Kind kind = (AArch64Kind) expectedValue.getPlatformKind();
+ assert kind.isInteger();
+ final int size = kind.getSizeInBytes() * Byte.SIZE;
+
+ Register address = asRegister(addressValue);
+ Register result = asRegister(resultValue);
+ Register newVal = asRegister(newValue);
+ if (masm.supports(CPUFeature.LSE) || masm.isFlagSet(Flag.UseLSE)) {
+ Register expected = asRegister(expectedValue);
+ masm.mov(size, result, expected);
+ masm.cas(size, expected, newVal, address, true /*acquire*/, true /*release*/);
+ AArch64Compare.gpCompare(masm, resultValue, expectedValue);
+ } else {
+ // We could avoid using a scratch register here, by reusing resultValue for the stlxr
+ // success flag and issue a mov resultValue, expectedValue in case of success before
+ // returning.
+ Register scratch = asRegister(scratchValue);
+ Label retry = new Label();
+ Label fail = new Label();
+ masm.bind(retry);
+ masm.ldaxr(size, result, address);
+ AArch64Compare.gpCompare(masm, resultValue, expectedValue);
+ masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, fail);
+ masm.stlxr(size, scratch, newVal, address);
+ // if scratch == 0 then write successful, else retry.
+ masm.cbnz(32, scratch, retry);
+ masm.bind(fail);
+ }
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,9 +37,7 @@
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.aarch64.AArch64Address;
-import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister;
import org.graalvm.compiler.core.common.LIRKind;
@@ -339,60 +337,6 @@
}
}
- /**
- * Compare and swap instruction. Does the following atomically: <code>
- * CAS(newVal, expected, address):
- * oldVal = *address
- * if oldVal == expected:
- * *address = newVal
- * return oldVal
- * </code>
- */
- @Opcode("CAS")
- public static class CompareAndSwapOp extends AArch64LIRInstruction {
- public static final LIRInstructionClass<CompareAndSwapOp> TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
-
- @Def protected AllocatableValue resultValue;
- @Alive protected Value expectedValue;
- @Alive protected AllocatableValue newValue;
- @Alive protected AllocatableValue addressValue;
- @Temp protected AllocatableValue scratchValue;
-
- public CompareAndSwapOp(AllocatableValue result, Value expectedValue, AllocatableValue newValue, AllocatableValue addressValue, AllocatableValue scratch) {
- super(TYPE);
- this.resultValue = result;
- this.expectedValue = expectedValue;
- this.newValue = newValue;
- this.addressValue = addressValue;
- this.scratchValue = scratch;
- }
-
- @Override
- public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
- AArch64Kind kind = (AArch64Kind) expectedValue.getPlatformKind();
- assert kind.isInteger();
- final int size = kind.getSizeInBytes() * Byte.SIZE;
-
- Register address = asRegister(addressValue);
- Register result = asRegister(resultValue);
- Register newVal = asRegister(newValue);
- Register scratch = asRegister(scratchValue);
- // We could avoid using a scratch register here, by reusing resultValue for the stlxr
- // success flag and issue a mov resultValue, expectedValue in case of success before
- // returning.
- Label retry = new Label();
- Label fail = new Label();
- masm.bind(retry);
- masm.ldaxr(size, result, address);
- AArch64Compare.gpCompare(masm, resultValue, expectedValue);
- masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, fail);
- masm.stlxr(size, scratch, newVal, address);
- // if scratch == 0 then write successful, else retry.
- masm.cbnz(32, scratch, retry);
- masm.bind(fail);
- }
- }
-
private static void emitStore(@SuppressWarnings("unused") CompilationResultBuilder crb, AArch64MacroAssembler masm, AArch64Kind kind, AArch64Address dst, Value src) {
int destSize = kind.getSizeInBytes() * Byte.SIZE;
if (kind.isInteger()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -71,8 +71,10 @@
@Def({REG}) protected Value resultValue;
@Alive({REG}) protected Value array1Value;
@Alive({REG}) protected Value array2Value;
- @Alive({REG}) protected Value length1Value;
- @Alive({REG}) protected Value length2Value;
+ @Use({REG}) protected Value length1Value;
+ @Use({REG}) protected Value length2Value;
+ @Temp({REG}) protected Value length1ValueTemp;
+ @Temp({REG}) protected Value length2ValueTemp;
@Temp({REG}) protected Value temp1;
@Temp({REG}) protected Value temp2;
@@ -92,8 +94,14 @@
this.resultValue = result;
this.array1Value = array1;
this.array2Value = array2;
+ /*
+ * The length values are inputs but are also killed like temporaries so need both Use and
+ * Temp annotations, which will only work with fixed registers.
+ */
this.length1Value = length1;
this.length2Value = length2;
+ this.length1ValueTemp = length1;
+ this.length2ValueTemp = length2;
// Allocate some temporaries.
this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
import java.util.Arrays;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.LIRValueUtil;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp.prune;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java Thu Apr 26 17:59:02 2018 +0200
@@ -78,8 +78,8 @@
import java.util.EnumSet;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Assembler.LabelHint;
import org.graalvm.compiler.asm.Label;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
import java.util.Arrays;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.sparc.SPARCAddress;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
import java.util.HashSet;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue;
import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,9 +33,9 @@
import java.util.Arrays;
import java.util.EnumSet;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.core.common.FieldIntrospection;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.FieldsScanner;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,8 +30,8 @@
import java.util.Collections;
import java.util.EnumSet;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.CounterKey;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
import java.util.ArrayList;
import java.util.EnumSet;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.GraalError;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/RegisterAllocationPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.lir.alloc;
+
+import org.graalvm.compiler.lir.phases.AllocationPhase;
+
+/**
+ * Marker class for register allocation phases.
+ */
+public abstract class RegisterAllocationPhase extends AllocationPhase {
+ private boolean neverSpillConstants;
+
+ public void setNeverSpillConstants(boolean neverSpillConstants) {
+ this.neverSpillConstants = neverSpillConstants;
+ }
+
+ public boolean getNeverSpillConstants() {
+ return neverSpillConstants;
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
import java.util.BitSet;
import java.util.EnumSet;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,8 +35,8 @@
import java.util.BitSet;
import java.util.EnumSet;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
@@ -160,12 +160,14 @@
intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops());
try {
+ final BitSet liveGenScratch = new BitSet(liveSize);
+ final BitSet liveKillScratch = new BitSet(liveSize);
// iterate all blocks
for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) {
try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) {
- final BitSet liveGen = new BitSet(liveSize);
- final BitSet liveKill = new BitSet(liveSize);
+ liveGenScratch.clear();
+ liveKillScratch.clear();
ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
int numInst = instructions.size();
@@ -173,8 +175,8 @@
ValueConsumer useConsumer = (operand, mode, flags) -> {
if (isVariable(operand)) {
int operandNum = allocator.operandNumber(operand);
- if (!liveKill.get(operandNum)) {
- liveGen.set(operandNum);
+ if (!liveKillScratch.get(operandNum)) {
+ liveGenScratch.set(operandNum);
if (debug.isLogEnabled()) {
debug.log("liveGen for operand %d(%s)", operandNum, operand);
}
@@ -185,14 +187,14 @@
}
if (allocator.detailedAsserts) {
- verifyInput(block, liveKill, operand);
+ verifyInput(block, liveKillScratch, operand);
}
};
ValueConsumer stateConsumer = (operand, mode, flags) -> {
if (LinearScan.isVariableOrRegister(operand)) {
int operandNum = allocator.operandNumber(operand);
- if (!liveKill.get(operandNum)) {
- liveGen.set(operandNum);
+ if (!liveKillScratch.get(operandNum)) {
+ liveGenScratch.set(operandNum);
if (debug.isLogEnabled()) {
debug.log("liveGen in state for operand %d(%s)", operandNum, operand);
}
@@ -202,7 +204,7 @@
ValueConsumer defConsumer = (operand, mode, flags) -> {
if (isVariable(operand)) {
int varNum = allocator.operandNumber(operand);
- liveKill.set(varNum);
+ liveKillScratch.set(varNum);
if (debug.isLogEnabled()) {
debug.log("liveKill for operand %d(%s)", varNum, operand);
}
@@ -217,7 +219,7 @@
* be processed in live sets. Process them only in debug mode so that
* this can be checked
*/
- verifyTemp(liveKill, operand);
+ verifyTemp(liveKillScratch, operand);
}
};
@@ -239,10 +241,11 @@
} // end of instruction iteration
BlockData blockSets = allocator.getBlockData(block);
- blockSets.liveGen = liveGen;
- blockSets.liveKill = liveKill;
- blockSets.liveIn = new BitSet(liveSize);
- blockSets.liveOut = new BitSet(liveSize);
+ blockSets.liveGen = trimClone(liveGenScratch);
+ blockSets.liveKill = trimClone(liveKillScratch);
+ // sticky size, will get non-sticky in computeGlobalLiveSets
+ blockSets.liveIn = new BitSet(0);
+ blockSets.liveOut = new BitSet(0);
if (debug.isLogEnabled()) {
debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen);
@@ -292,7 +295,7 @@
boolean changeOccurred;
boolean changeOccurredInBlock;
int iterationCount = 0;
- BitSet liveOut = new BitSet(allocator.liveSetSize()); // scratch set for calculations
+ BitSet scratch = new BitSet(allocator.liveSetSize()); // scratch set for calculations
/*
* Perform a backward dataflow analysis to compute liveOut and liveIn for each block.
@@ -315,22 +318,16 @@
*/
int n = block.getSuccessorCount();
if (n > 0) {
- liveOut.clear();
+ scratch.clear();
// block has successors
if (n > 0) {
for (AbstractBlockBase<?> successor : block.getSuccessors()) {
- liveOut.or(allocator.getBlockData(successor).liveIn);
+ scratch.or(allocator.getBlockData(successor).liveIn);
}
}
- if (!blockSets.liveOut.equals(liveOut)) {
- /*
- * A change occurred. Swap the old and new live out sets to avoid
- * copying.
- */
- BitSet temp = blockSets.liveOut;
- blockSets.liveOut = liveOut;
- liveOut = temp;
+ if (!blockSets.liveOut.equals(scratch)) {
+ blockSets.liveOut = trimClone(scratch);
changeOccurred = true;
changeOccurredInBlock = true;
@@ -344,13 +341,20 @@
*
* Note: liveIn has to be computed only in first iteration or if liveOut
* has changed!
+ *
+ * Note: liveIn set can only grow, never shrink. No need to clear it.
*/
BitSet liveIn = blockSets.liveIn;
- liveIn.clear();
+ /*
+ * BitSet#or will call BitSet#ensureSize (since the bit set is of length
+ * 0 initially) and set sticky to false
+ */
liveIn.or(blockSets.liveOut);
liveIn.andNot(blockSets.liveKill);
liveIn.or(blockSets.liveGen);
+ liveIn.clone(); // trimToSize()
+
if (debug.isLogEnabled()) {
debug.log("block %d: livein = %s, liveout = %s", block.getId(), liveIn, blockSets.liveOut);
}
@@ -384,6 +388,20 @@
}
}
+ /**
+ * Creates a trimmed copy a bit set.
+ *
+ * {@link BitSet#clone()} cannot be used since it will not {@linkplain BitSet#trimToSize trim}
+ * the array if the bit set is {@linkplain BitSet#sizeIsSticky sticky}.
+ */
+ @SuppressWarnings("javadoc")
+ private static BitSet trimClone(BitSet set) {
+ BitSet trimmedSet = new BitSet(0); // zero-length words array, sticky
+ trimmedSet.or(set); // words size ensured to be words-in-use of set,
+ // also makes it non-sticky
+ return trimmedSet;
+ }
+
@SuppressWarnings("try")
protected void reportFailure(int numBlocks) {
try (DebugContext.Scope s = debug.forceLog()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,26 +23,20 @@
package org.graalvm.compiler.lir.alloc.lsra;
import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
+import org.graalvm.compiler.lir.alloc.RegisterAllocationPhase;
import org.graalvm.compiler.lir.alloc.lsra.ssa.SSALinearScan;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
-import org.graalvm.compiler.lir.phases.AllocationPhase;
import jdk.vm.ci.code.TargetDescription;
-public final class LinearScanPhase extends AllocationPhase {
-
- private boolean neverSpillConstants;
-
- public void setNeverSpillConstants(boolean neverSpillConstants) {
- this.neverSpillConstants = neverSpillConstants;
- }
+public final class LinearScanPhase extends RegisterAllocationPhase {
@Override
protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
MoveFactory spillMoveFactory = context.spillMoveFactory;
RegisterAllocationConfig registerAllocationConfig = context.registerAllocationConfig;
- final LinearScan allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig, lirGenRes.getLIR().linearScanOrder(), neverSpillConstants);
+ final LinearScan allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig, lirGenRes.getLIR().linearScanOrder(), getNeverSpillConstants());
allocator.allocate(target, lirGenRes, context);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.lir.alloc.lsra;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
import org.graalvm.compiler.debug.Indent;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
import java.util.ArrayList;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.Indent;
import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.alloc.RegisterAllocationPhase;
import org.graalvm.compiler.lir.alloc.trace.TraceAllocationPhase.TraceAllocationContext;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
-import org.graalvm.compiler.lir.phases.AllocationPhase;
import org.graalvm.compiler.lir.ssa.SSAUtil;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
@@ -47,7 +47,7 @@
* <a href="http://dx.doi.org/10.1145/2972206.2972211">"Trace-based Register Allocation in a JIT
* Compiler"</a> by Josef Eisl et al.
*/
-public final class TraceRegisterAllocationPhase extends AllocationPhase {
+public final class TraceRegisterAllocationPhase extends RegisterAllocationPhase {
public static class Options {
// @formatter:off
@@ -67,9 +67,20 @@
public static final CounterKey globalStackSlots = DebugContext.counter("TraceRA[GlobalStackSlots]");
public static final CounterKey allocatedStackSlots = DebugContext.counter("TraceRA[AllocatedStackSlots]");
+ private final TraceBuilderPhase traceBuilder;
+ private final GlobalLivenessAnalysisPhase livenessAnalysis;
+
+ public TraceRegisterAllocationPhase() {
+ this.traceBuilder = new TraceBuilderPhase();
+ this.livenessAnalysis = new GlobalLivenessAnalysisPhase();
+ }
+
@Override
@SuppressWarnings("try")
protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
+ traceBuilder.apply(target, lirGenRes, context);
+ livenessAnalysis.apply(target, lirGenRes, context);
+
MoveFactory spillMoveFactory = context.spillMoveFactory;
RegisterAllocationConfig registerAllocationConfig = context.registerAllocationConfig;
LIR lir = lirGenRes.getLIR();
@@ -80,8 +91,8 @@
TraceAllocationContext traceContext = new TraceAllocationContext(spillMoveFactory, registerAllocationConfig, resultTraces, livenessInfo);
AllocatableValue[] cachedStackSlots = Options.TraceRACacheStackSlots.getValue(lir.getOptions()) ? new AllocatableValue[lir.numVariables()] : null;
- // currently this is not supported
- boolean neverSpillConstant = false;
+ boolean neverSpillConstant = getNeverSpillConstants();
+ assert !neverSpillConstant : "currently this is not supported";
final TraceRegisterAllocationPolicy plan = DefaultTraceRegisterAllocationPolicy.allocationPolicy(target, lirGenRes, spillMoveFactory, registerAllocationConfig, cachedStackSlots, resultTraces,
neverSpillConstant, livenessInfo, lir.getOptions());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
import java.util.List;
import java.util.function.Consumer;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.asm.AbstractAddress;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.code.CompilationResult;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
*/
package org.graalvm.compiler.lir.gen;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,8 +30,8 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.lir.LIRInsertionBuffer;
import org.graalvm.compiler.lir.LIRInstruction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/AllocationStage.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/AllocationStage.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,6 @@
import org.graalvm.compiler.debug.Assertions;
import org.graalvm.compiler.lir.alloc.AllocationStageVerifier;
import org.graalvm.compiler.lir.alloc.lsra.LinearScanPhase;
-import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase;
-import org.graalvm.compiler.lir.alloc.trace.TraceBuilderPhase;
import org.graalvm.compiler.lir.alloc.trace.TraceRegisterAllocationPhase;
import org.graalvm.compiler.lir.dfa.LocationMarkerPhase;
import org.graalvm.compiler.lir.dfa.MarkBasePointersPhase;
@@ -42,8 +40,6 @@
public AllocationStage(OptionValues options) {
appendPhase(new MarkBasePointersPhase());
if (TraceRA.getValue(options)) {
- appendPhase(new TraceBuilderPhase());
- appendPhase(new GlobalLivenessAnalysisPhase());
appendPhase(new TraceRegisterAllocationPhase());
} else {
appendPhase(new LinearScanPhase());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyAllocationStage.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyAllocationStage.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,6 @@
import static org.graalvm.compiler.core.common.GraalOptions.TraceRA;
import org.graalvm.compiler.lir.alloc.lsra.LinearScanPhase;
-import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase;
-import org.graalvm.compiler.lir.alloc.trace.TraceBuilderPhase;
import org.graalvm.compiler.lir.alloc.trace.TraceRegisterAllocationPhase;
import org.graalvm.compiler.lir.dfa.LocationMarkerPhase;
import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
@@ -36,8 +34,6 @@
public class EconomyAllocationStage extends LIRPhaseSuite<AllocationContext> {
public EconomyAllocationStage(OptionValues options) {
if (TraceRA.getValue(options)) {
- appendPhase(new TraceBuilderPhase());
- appendPhase(new GlobalLivenessAnalysisPhase());
appendPhase(new TraceRegisterAllocationPhase());
} else {
appendPhase(new LinearScanPhase());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -31,8 +31,8 @@
import java.util.Deque;
import java.util.EnumSet;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.debug.CounterKey;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
import java.util.EnumSet;
import java.util.PriorityQueue;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
*/
package org.graalvm.compiler.lir.util;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,7 @@
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.util.UnsignedLong;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.loop.InductionVariable.Direction;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.ConstantNode;
@@ -223,34 +224,37 @@
return loop.loopBegin().getOverflowGuard();
}
+ @SuppressWarnings("try")
public GuardingNode createOverFlowGuard() {
GuardingNode overflowGuard = getOverFlowGuard();
if (overflowGuard != null) {
return overflowGuard;
}
- IntegerStamp stamp = (IntegerStamp) iv.valueNode().stamp(NodeView.DEFAULT);
- StructuredGraph graph = iv.valueNode().graph();
- CompareNode cond; // we use a negated guard with a < condition to achieve a >=
- ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
- if (iv.direction() == Direction.Up) {
- ValueNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
- if (oneOff) {
- v1 = sub(graph, v1, one);
+ try (DebugCloseable position = loop.loopBegin().withNodeSourcePosition()) {
+ IntegerStamp stamp = (IntegerStamp) iv.valueNode().stamp(NodeView.DEFAULT);
+ StructuredGraph graph = iv.valueNode().graph();
+ CompareNode cond; // we use a negated guard with a < condition to achieve a >=
+ ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
+ if (iv.direction() == Direction.Up) {
+ ValueNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
+ if (oneOff) {
+ v1 = sub(graph, v1, one);
+ }
+ cond = graph.unique(new IntegerLessThanNode(v1, end));
+ } else {
+ assert iv.direction() == Direction.Down;
+ ValueNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
+ if (oneOff) {
+ v1 = add(graph, v1, one);
+ }
+ cond = graph.unique(new IntegerLessThanNode(end, v1));
}
- cond = graph.unique(new IntegerLessThanNode(v1, end));
- } else {
- assert iv.direction() == Direction.Down;
- ValueNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
- if (oneOff) {
- v1 = add(graph, v1, one);
- }
- cond = graph.unique(new IntegerLessThanNode(end, v1));
+ assert graph.getGuardsStage().allowsFloatingGuards();
+ overflowGuard = graph.unique(new GuardNode(cond, AbstractBeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
+ JavaConstant.NULL_POINTER)); // TODO gd: use speculation
+ loop.loopBegin().setOverflowGuard(overflowGuard);
+ return overflowGuard;
}
- assert graph.getGuardsStage().allowsFloatingGuards();
- overflowGuard = graph.unique(new GuardNode(cond, AbstractBeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
- JavaConstant.NULL_POINTER)); // TODO gd: use speculation
- loop.loopBegin().setOverflowGuard(overflowGuard);
- return overflowGuard;
}
public IntegerStamp getStamp() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,9 +26,9 @@
import java.util.LinkedList;
import java.util.Queue;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.type.IntegerStamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
import java.util.Deque;
import java.util.Iterator;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.util.LinkedList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.loop;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Graph;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,9 +27,9 @@
import java.util.LinkedList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.LoopBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.List;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.NodeClass;
import jdk.vm.ci.meta.Assumptions;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FieldLocationIdentity.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FieldLocationIdentity.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import jdk.vm.ci.meta.JavaKind.FormatWithToString;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ResolvedJavaField;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,9 +37,9 @@
import java.util.SortedMap;
import java.util.TreeMap;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.util.TypeReader;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
import java.util.Iterator;
import java.util.Objects;
-import org.graalvm.collections.Pair;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.util.FrequencyEncoder;
import org.graalvm.compiler.core.common.util.TypeConversion;
--- /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/GraphSpeculationLog.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018, 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.nodes;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.SpeculationLog;
+
+/**
+ * A wrapper around a {@link SpeculationLog} instance.
+ *
+ * This should be used when the wrapped instance may be accessed by multiple threads. Due to races,
+ * such an instance can return true for a call to {@link SpeculationLog#maySpeculate} but still fail
+ * (i.e. raise an {@link IllegalArgumentException}) when {@link SpeculationLog#speculate} is called.
+ *
+ * A {@link GraphSpeculationLog} must only be used by a single thread and is typically closely
+ * coupled with a {@link StructuredGraph} (hence the name).
+ */
+public final class GraphSpeculationLog implements SpeculationLog {
+
+ private final SpeculationLog log;
+ private final EconomicMap<SpeculationReason, JavaConstant> speculations;
+
+ public GraphSpeculationLog(SpeculationLog log) {
+ this.log = log;
+ this.speculations = EconomicMap.create();
+ }
+
+ /**
+ * Unwraps {@code log} if it is a {@link GraphSpeculationLog}.
+ */
+ public static SpeculationLog unwrap(SpeculationLog log) {
+ if (log instanceof GraphSpeculationLog) {
+ return ((GraphSpeculationLog) log).log;
+ }
+ return log;
+ }
+
+ /**
+ * Determines if the compiler is allowed to speculate with {@code reason}. Note that a
+ * {@code true} return value guarantees that a subsequent call to
+ * {@link #speculate(SpeculationReason)} with an argument {@linkplain Object#equals(Object)
+ * equal} to {@code reason} will succeed.
+ */
+ @Override
+ public boolean maySpeculate(SpeculationReason reason) {
+ JavaConstant speculation = speculations.get(reason);
+ if (speculation == null) {
+ if (log.maySpeculate(reason)) {
+ try {
+ speculation = log.speculate(reason);
+ speculations.put(reason, speculation);
+ } catch (IllegalArgumentException e) {
+ // The speculation was disabled by another thread in between
+ // the call to log.maySpeculate and log.speculate
+ speculation = null;
+ }
+ }
+ }
+ return speculation != null;
+ }
+
+ @Override
+ public JavaConstant speculate(SpeculationReason reason) {
+ if (maySpeculate(reason)) {
+ JavaConstant speculation = speculations.get(reason);
+ assert speculation != null;
+ return speculation;
+ }
+ throw new IllegalArgumentException("Cannot make speculation with reason " + reason + " as it is known to fail");
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof GraphSpeculationLog) {
+ GraphSpeculationLog that = (GraphSpeculationLog) obj;
+ return this.log == that.log;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return log.hashCode();
+ }
+
+ @Override
+ public void collectFailedSpeculations() {
+ log.collectFailedSpeculations();
+ }
+
+ /**
+ * Returns if this log has speculations.
+ *
+ * @return true if {@link #maySpeculate(SpeculationReason)} has ever returned {@code true} for
+ * this object
+ */
+ @Override
+ public boolean hasSpeculations() {
+ return !speculations.isEmpty();
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,8 +30,8 @@
import java.util.Iterator;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,14 +24,12 @@
import jdk.vm.ci.meta.MetaUtil;
import jdk.vm.ci.meta.ResolvedJavaMethod;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.compiler.core.common.GraalOptions;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.options.OptionValues;
import java.util.ArrayList;
import java.util.List;
@@ -56,6 +54,8 @@
* {@link #addDecision} to log negative decisions.
*/
public class InliningLog {
+ private static final String TREE_NODE = "\u251c\u2500\u2500";
+ private static final String LAST_TREE_NODE = "\u2514\u2500\u2500";
public static final class Decision {
private final boolean positive;
@@ -88,7 +88,8 @@
@Override
public String toString() {
- return String.format("<%s> %s: %s", phase, target != null ? target.format("%H.%n(%p)") : "", reason);
+ return String.format("<%s> %s: %s, %s", phase, target != null ? target.format("%H.%n(%p)") : "", positive ? "yes" : "no",
+ reason);
}
}
@@ -114,9 +115,9 @@
public String positionString() {
if (parent == null) {
- return "<root>";
+ return "compilation of " + target.format("%H.%n(%p)");
}
- return MetaUtil.appendLocation(new StringBuilder(100), parent.target, getBci()).toString();
+ return "at " + MetaUtil.appendLocation(new StringBuilder(100), parent.target, getBci()).toString();
}
public int getBci() {
@@ -126,13 +127,13 @@
private final Callsite root;
private final EconomicMap<Invokable, Callsite> leaves;
- private final OptionValues options;
+ private final boolean enabled;
- public InliningLog(ResolvedJavaMethod rootMethod, OptionValues options) {
+ public InliningLog(ResolvedJavaMethod rootMethod, boolean enabled) {
this.root = new Callsite(null, null);
this.root.target = rootMethod;
this.leaves = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE);
- this.options = options;
+ this.enabled = enabled;
}
/**
@@ -142,15 +143,22 @@
* logged after replacing an {@link Invoke} with a graph. In this case, the node replacement map
* and the {@link InliningLog} of the inlined graph must be provided.
*/
- public void addDecision(Invokable invoke, boolean positive, String reason, String phase, EconomicMap<Node, Node> replacements, InliningLog calleeLog) {
+ public void addDecision(Invokable invoke, boolean positive, String phase, EconomicMap<Node, Node> replacements, InliningLog calleeLog, String reason, Object... args) {
+ if (!enabled) {
+ return;
+ }
assert leaves.containsKey(invoke);
- assert (!positive && replacements == null && calleeLog == null) || (positive && replacements != null && calleeLog != null);
+ assert (!positive && replacements == null && calleeLog == null) || (positive && replacements != null && calleeLog != null) ||
+ (positive && replacements == null && calleeLog == null);
Callsite callsite = leaves.get(invoke);
callsite.target = callsite.invoke.getTargetMethod();
- Decision decision = new Decision(positive, reason, phase, invoke.getTargetMethod());
+ Decision decision = new Decision(positive, String.format(reason, args), phase, invoke.getTargetMethod());
callsite.decisions.add(decision);
if (positive) {
leaves.removeKey(invoke);
+ if (calleeLog == null) {
+ return;
+ }
EconomicMap<Callsite, Callsite> mapping = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE);
for (Callsite calleeChild : calleeLog.root.children) {
Callsite child = callsite.addChild(calleeChild.invoke);
@@ -227,7 +235,7 @@
mapping.put(replacementSite, site);
site.target = replacementSite.target;
site.decisions.addAll(replacementSite.decisions);
- site.invoke = replacementSite.invoke != null && replacementSite.invoke.asFixedNode().isAlive() ? (Invokable) replacements.get(replacementSite.invoke.asFixedNode()) : null;
+ site.invoke = replacementSite.invoke != null && replacementSite.invoke.isAlive() ? (Invokable) replacements.get(replacementSite.invoke.asFixedNode()) : null;
for (Callsite replacementChild : replacementSite.children) {
Callsite child = new Callsite(site, null);
site.children.add(child);
@@ -253,7 +261,7 @@
private UpdateScope noUpdates = new UpdateScope((oldNode, newNode) -> {
});
- private UpdateScope activated = null;
+ private UpdateScope currentUpdateScope = null;
/**
* Used to designate scopes in which {@link Invokable} registration or cloning should be handled
@@ -267,17 +275,17 @@
}
public void activate() {
- if (activated != null) {
+ if (currentUpdateScope != null) {
throw GraalError.shouldNotReachHere("InliningLog updating already set.");
}
- activated = this;
+ currentUpdateScope = this;
}
@Override
public void close() {
- if (GraalOptions.TraceInlining.getValue(options)) {
- assert activated != null;
- activated = null;
+ if (enabled) {
+ assert currentUpdateScope != null;
+ currentUpdateScope = null;
}
}
@@ -287,10 +295,10 @@
}
public BiConsumer<Invokable, Invokable> getUpdateScope() {
- if (activated == null) {
+ if (currentUpdateScope == null) {
return null;
}
- return activated.getUpdater();
+ return currentUpdateScope.getUpdater();
}
/**
@@ -305,7 +313,7 @@
* @return a bound {@link UpdateScope} object, or a {@code null} if tracing is disabled
*/
public UpdateScope openUpdateScope(BiConsumer<Invokable, Invokable> updater) {
- if (GraalOptions.TraceInlining.getValue(options)) {
+ if (enabled) {
UpdateScope scope = new UpdateScope(updater);
scope.activate();
return scope;
@@ -324,7 +332,7 @@
* @see #openUpdateScope
*/
public UpdateScope openDefaultUpdateScope() {
- if (GraalOptions.TraceInlining.getValue(options)) {
+ if (enabled) {
noUpdates.activate();
return noUpdates;
} else {
@@ -332,6 +340,97 @@
}
}
+ private RootScope currentRootScope = null;
+
+ /**
+ * Used to change the current effective root of the method being compiled.
+ *
+ * This root scope is used in situations in which a phase does its own ad-hoc inlining, in which
+ * it replaces an Invoke with other nodes, some of which may be other Invokes. The prime example
+ * for this is the bytecode parser, which does not create separate graphs with their own
+ * inlining logs when inlining an Invoke, but instead continues recursively parsing the graph
+ * corresponding to the Invoke.
+ *
+ * Root scopes can be nested.
+ *
+ * @see #openRootScope
+ */
+ public final class RootScope implements AutoCloseable {
+ private final RootScope parent;
+ private Callsite replacementRoot;
+
+ public RootScope(RootScope parent, Callsite replacementRoot) {
+ this.parent = parent;
+ this.replacementRoot = replacementRoot;
+ }
+
+ void activate() {
+ currentRootScope = this;
+ }
+
+ public Invokable getInvoke() {
+ return replacementRoot.invoke;
+ }
+
+ @Override
+ public void close() {
+ if (enabled) {
+ assert currentRootScope != null;
+ removeLeafCallsite(replacementRoot.invoke);
+ currentRootScope = parent;
+ }
+ }
+ }
+
+ public final class PlaceholderInvokable implements Invokable {
+ private int bci;
+ private ResolvedJavaMethod method;
+
+ public PlaceholderInvokable(ResolvedJavaMethod method, int bci) {
+ this.method = method;
+ this.bci = bci;
+ }
+
+ @Override
+ public ResolvedJavaMethod getTargetMethod() {
+ return method;
+ }
+
+ @Override
+ public int bci() {
+ return bci;
+ }
+
+ @Override
+ public boolean isAlive() {
+ return false;
+ }
+
+ @Override
+ public FixedNode asFixedNode() {
+ throw new UnsupportedOperationException("Parsed invokable is a placeholder, not a concrete node.");
+ }
+ }
+
+ public RootScope openRootScope(ResolvedJavaMethod target, int bci) {
+ return openRootScope(new PlaceholderInvokable(target, bci));
+ }
+
+ public RootScope openRootScope(Invokable invoke) {
+ if (enabled) {
+ if (!leaves.containsKey(invoke)) {
+ // Create the invoke if it was not added to the graph yet.
+ trackNewCallsite(invoke);
+ }
+ RootScope scope = new RootScope(currentRootScope, leaves.get(invoke));
+ scope.replacementRoot.target = invoke.getTargetMethod();
+ scope.activate();
+ return scope;
+ } else {
+ return null;
+ }
+ }
+
public boolean containsLeafCallsite(Invokable invokable) {
return leaves.containsKey(invokable);
}
@@ -342,11 +441,16 @@
public void trackNewCallsite(Invokable invoke) {
assert !leaves.containsKey(invoke);
- Callsite callsite = new Callsite(root, invoke);
- root.children.add(callsite);
+ Callsite currentRoot = findCurrentRoot();
+ Callsite callsite = new Callsite(currentRoot, invoke);
+ currentRoot.children.add(callsite);
leaves.put(invoke, callsite);
}
+ private Callsite findCurrentRoot() {
+ return currentRootScope != null ? currentRootScope.replacementRoot : root;
+ }
+
public void trackDuplicatedCallsite(Invokable sibling, Invokable newInvoke) {
Callsite siblingCallsite = leaves.get(sibling);
Callsite parentCallsite = siblingCallsite.parent;
@@ -361,7 +465,19 @@
callsite.invoke = newInvoke;
}
- public String formatAsTree() {
+ /**
+ * Formats the inlining log as a hierarchical tree.
+ *
+ * @param nullIfEmpty specifies whether null should be returned if there are no inlining
+ * decisions
+ * @return the tree representation of the inlining log
+ */
+ public String formatAsTree(boolean nullIfEmpty) {
+ assert root.decisions.isEmpty();
+ assert !root.children.isEmpty() || leaves.isEmpty();
+ if (nullIfEmpty && root.children.isEmpty()) {
+ return null;
+ }
StringBuilder builder = new StringBuilder(512);
formatAsTree(root, "", builder);
return builder.toString();
@@ -369,12 +485,20 @@
private void formatAsTree(Callsite site, String indent, StringBuilder builder) {
String position = site.positionString();
- builder.append(indent).append("at ").append(position).append(": ");
+ builder.append(indent).append(position).append(": ");
if (site.decisions.isEmpty()) {
+ if (site.parent != null) {
+ builder.append("(no decisions made about ").append(site.target != null ? site.target.format("%H.%n(%p)") : "").append(")");
+ }
+ builder.append(System.lineSeparator());
+ } else if (site.decisions.size() == 1) {
+ builder.append(site.decisions.get(0).toString());
builder.append(System.lineSeparator());
} else {
+ builder.append(System.lineSeparator());
for (Decision decision : site.decisions) {
- builder.append(decision.toString());
+ String node = (decision == site.decisions.get(site.decisions.size() - 1)) ? LAST_TREE_NODE : TREE_NODE;
+ builder.append(indent + " " + node).append(decision.toString());
builder.append(System.lineSeparator());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,10 @@
int bci();
+ default boolean isAlive() {
+ return asFixedNode().isAlive();
+ }
+
FixedNode asFixedNode();
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -41,7 +41,7 @@
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import java.util.Map;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import java.util.Map;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
@NodeInfo(allowedUsageTypes = {Memory}, cycles = CYCLES_0, size = SIZE_0)
public final class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopExitNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopExitNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -105,9 +105,7 @@
Node prev = this.predecessor();
while (tool.allUsagesAvailable() && prev instanceof BeginNode && prev.hasNoUsages()) {
AbstractBeginNode begin = (AbstractBeginNode) prev;
- if (begin.getNodeSourcePosition() != null || this.getNodeSourcePosition() == null || this.getNodeSourcePosition().isPlaceholder()) {
- this.setNodeSourcePosition(begin.getNodeSourcePosition());
- }
+ this.setNodeSourcePosition(begin.getNodeSourcePosition());
prev = prev.predecessor();
graph().removeFixed(begin);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,9 +24,9 @@
import java.util.EnumMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaKind.FormatWithToString;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StartNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StartNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* The start node of a graph.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.core.common.CancellationBailoutException;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.GraalOptions;
@@ -359,12 +359,16 @@
this.compilationId = compilationId;
this.entryBCI = entryBCI;
this.assumptions = assumptions;
- this.speculationLog = speculationLog;
+ if (speculationLog != null && !(speculationLog instanceof GraphSpeculationLog)) {
+ this.speculationLog = new GraphSpeculationLog(speculationLog);
+ } else {
+ this.speculationLog = speculationLog;
+ }
this.useProfilingInfo = useProfilingInfo;
this.trackNodeSourcePosition = trackNodeSourcePosition;
assert trackNodeSourcePosition != null;
this.cancellable = cancellable;
- this.inliningLog = new InliningLog(rootMethod, options);
+ this.inliningLog = new InliningLog(rootMethod, GraalOptions.TraceInlining.getValue(options));
this.callerContext = context;
}
@@ -480,7 +484,10 @@
public void logInliningTree() {
if (GraalOptions.TraceInlining.getValue(getOptions())) {
- TTY.println(getInliningLog().formatAsTree());
+ String formattedTree = getInliningLog().formatAsTree(true);
+ if (formattedTree != null) {
+ TTY.println(formattedTree);
+ }
}
}
@@ -518,6 +525,7 @@
copy.isAfterFloatingReadPhase = isAfterFloatingReadPhase;
copy.hasValueProxies = hasValueProxies;
copy.isAfterExpandLogic = isAfterExpandLogic;
+ copy.trackNodeSourcePosition = trackNodeSourcePosition;
EconomicMap<Node, Node> replacements = EconomicMap.create(Equivalence.IDENTITY);
replacements.put(start, copy.start);
UnmodifiableEconomicMap<Node, Node> duplicates;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
import org.graalvm.compiler.nodes.LoopEndNode;
import org.graalvm.compiler.nodes.LoopExitNode;
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public final class Block extends AbstractBlockBase<Block> {
public static final Block[] EMPTY_ARRAY = new Block[0];
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.nodes.LoopBeginNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public final class HIRLoop extends Loop<Block> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/LocationSet.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/LocationSet.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
import java.util.Arrays;
import java.util.List;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public class LocationSet {
private LocationIdentity firstLocation;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/StringToBytesNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/StringToBytesNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.MetaAccessProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -46,7 +46,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/MembarNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/MembarNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* Creates a memory barrier.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -44,7 +44,7 @@
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.Constant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
import org.graalvm.compiler.nodes.NamedLocationIdentity;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.type.StampTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryLoadNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryLoadNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryStoreNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryStoreNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,15 +35,16 @@
import java.util.List;
import java.util.Map;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry;
import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.debug.Assertions;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
@@ -862,6 +863,7 @@
lateRegistrations = lateClassPlugins;
}
+ @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "string literal object identity used as sentinel")
private synchronized boolean closeLateRegistrations() {
if (lateRegistrations == null || lateRegistrations.className != CLOSED_LATE_CLASS_PLUGIN) {
lateRegistrations = new LateClassPlugins(lateRegistrations, CLOSED_LATE_CLASS_PLUGIN);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
import org.graalvm.compiler.nodes.memory.LIRLowerableAccess;
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* Low-level atomic compare-and-swap operation.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import static org.graalvm.compiler.nodeinfo.InputType.Memory;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorEnterNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorEnterNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* The {@code MonitorEnterNode} represents the acquisition of a monitor.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* The {@code MonitorExitNode} represents a monitor release. If it is the release of the monitor of
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,7 +38,7 @@
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* The {@code RawMonitorEnterNode} represents the acquisition of a monitor. The object needs to
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
@@ -53,8 +53,8 @@
@Input ValueNode expected;
@Input ValueNode newValue;
- protected final JavaKind valueKind;
- protected final LocationIdentity locationIdentity;
+ private final JavaKind valueKind;
+ private final LocationIdentity locationIdentity;
public UnsafeCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, JavaKind valueKind, LocationIdentity locationIdentity) {
super(TYPE, StampFactory.forKind(JavaKind.Boolean.getStackKind()));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* A special purpose store node that differs from {@link LogicCompareAndSwapNode} in that it returns
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import org.graalvm.compiler.nodes.ValueNodeUtil;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
@NodeInfo(allowedUsageTypes = {InputType.Memory, InputType.Guard}, cycles = CYCLES_2, size = SIZE_1)
public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import org.graalvm.compiler.nodes.extended.GuardedNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public interface Access extends GuardedNode, HeapAccess {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* Accesses a value at an memory address specified by an {@linkplain #address address}. The access
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* An {@link FixedAccessNode} that can be converted to a {@link FloatingAccessNode}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
import org.graalvm.compiler.nodes.FloatingGuardedNode;
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
@NodeInfo
public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -41,7 +41,7 @@
import org.graalvm.compiler.nodes.extended.GuardingNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* A floating read of a value from memory specified in terms of an object base and an object
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.nodes.memory;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* This interface marks nodes that access some memory location, and that have an edge to the last
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryCheckpoint.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryCheckpoint.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.FixedNodeInterface;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* This interface marks subclasses of {@link FixedNode} that kill a set of memory locations
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMap.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMap.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.nodes.memory;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* Maps a {@linkplain LocationIdentity location} to the last node that (potentially) wrote to the
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,15 +26,15 @@
import static org.graalvm.compiler.nodeinfo.InputType.Memory;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
@@ -44,7 +44,7 @@
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
@NodeInfo(allowedUsageTypes = {Extension, Memory}, cycles = CYCLES_0, size = SIZE_0)
public final class MemoryMapNode extends FloatingNode implements MemoryMap, MemoryNode, LIRLowerable {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryPhiNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryPhiNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* Memory {@code PhiNode}s merge memory dependencies at control flow merges.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -48,7 +48,7 @@
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.MetaAccessProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/MemoryProxy.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/MemoryProxy.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
package org.graalvm.compiler.nodes.spi;
import org.graalvm.compiler.nodes.memory.MemoryNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public interface MemoryProxy extends Proxy, MemoryNode {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
import java.util.List;
import java.util.function.BiFunction;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -54,7 +54,7 @@
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.nodes.spi.VirtualizableAllocation;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
// @formatter:off
@NodeInfo(nameTemplate = "Alloc {i#virtualObjects}",
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java Thu Apr 26 17:59:02 2018 +0200
@@ -61,6 +61,7 @@
import org.graalvm.compiler.options.OptionDescriptor;
import org.graalvm.compiler.options.OptionDescriptors;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
/**
* Processes static fields annotated with {@link Option}. An {@link OptionDescriptors}
@@ -218,7 +219,7 @@
}
}
- info.options.add(new OptionInfo(optionName, help, extraHelp, optionType, declaringClass, field));
+ info.options.add(new OptionInfo(optionName, annotation.type(), help, extraHelp, optionType, declaringClass, field));
}
private void createFiles(OptionsInfo info) {
@@ -243,6 +244,7 @@
out.println("");
out.println("import java.util.*;");
out.println("import " + OptionDescriptors.class.getPackage().getName() + ".*;");
+ out.println("import " + OptionType.class.getName() + ";");
out.println("");
out.println("public class " + optionsClassName + " implements " + OptionDescriptors.class.getSimpleName() + " {");
@@ -263,6 +265,7 @@
optionField = option.declaringClass + "." + option.field.getSimpleName();
}
out.println(" case \"" + name + "\": {");
+ OptionType optionType = option.optionType;
String type = option.type;
String help = option.help;
String[] extraHelp = option.extraHelp;
@@ -270,7 +273,8 @@
Name fieldName = option.field.getSimpleName();
out.printf(" return " + desc + ".create(\n");
out.printf(" /*name*/ \"%s\",\n", name);
- out.printf(" /*type*/ %s.class,\n", type);
+ out.printf(" /*optionType*/ %s.%s,\n", optionType.getDeclaringClass().getSimpleName(), optionType.name());
+ out.printf(" /*optionValueType*/ %s.class,\n", type);
out.printf(" /*help*/ \"%s\",\n", help);
if (extraHelp.length != 0) {
out.printf(" /*extraHelp*/ new String[] {\n");
@@ -332,14 +336,16 @@
static class OptionInfo implements Comparable<OptionInfo> {
final String name;
+ final OptionType optionType;
final String help;
final String[] extraHelp;
final String type;
final String declaringClass;
final VariableElement field;
- OptionInfo(String name, String help, String[] extraHelp, String type, String declaringClass, VariableElement field) {
+ OptionInfo(String name, OptionType optionType, String help, String[] extraHelp, String type, String declaringClass, VariableElement field) {
this.name = name;
+ this.optionType = optionType;
this.help = help;
this.extraHelp = extraHelp;
this.type = type;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/NestedBooleanOptionKeyTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/NestedBooleanOptionKeyTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -40,6 +40,7 @@
import org.graalvm.compiler.options.NestedBooleanOptionKey;
import org.graalvm.compiler.options.OptionDescriptor;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import org.junit.Test;
@@ -54,12 +55,12 @@
public static final OptionKey<Boolean> NestedOption2 = new NestedBooleanOptionKey(Master2, false);
}
- static final OptionDescriptor master0 = OptionDescriptor.create("Master0", Boolean.class, "", Options.class, "Master0", Master0);
- static final OptionDescriptor nestedOption0 = OptionDescriptor.create("NestedOption0", Boolean.class, "", Options.class, "NestedOption0", NestedOption0);
- static final OptionDescriptor master1 = OptionDescriptor.create("Master1", Boolean.class, "", Options.class, "Master1", Master1);
- static final OptionDescriptor nestedOption1 = OptionDescriptor.create("NestedOption1", Boolean.class, "", Options.class, "NestedOption1", NestedOption1);
- static final OptionDescriptor master2 = OptionDescriptor.create("Master2", Boolean.class, "", Options.class, "Master2", Master2);
- static final OptionDescriptor nestedOption2 = OptionDescriptor.create("NestedOption2", Boolean.class, "", Options.class, "NestedOption2", NestedOption2);
+ static final OptionDescriptor master0 = OptionDescriptor.create("Master0", OptionType.Debug, Boolean.class, "", Options.class, "Master0", Master0);
+ static final OptionDescriptor nestedOption0 = OptionDescriptor.create("NestedOption0", OptionType.Debug, Boolean.class, "", Options.class, "NestedOption0", NestedOption0);
+ static final OptionDescriptor master1 = OptionDescriptor.create("Master1", OptionType.Debug, Boolean.class, "", Options.class, "Master1", Master1);
+ static final OptionDescriptor nestedOption1 = OptionDescriptor.create("NestedOption1", OptionType.Debug, Boolean.class, "", Options.class, "NestedOption1", NestedOption1);
+ static final OptionDescriptor master2 = OptionDescriptor.create("Master2", OptionType.Debug, Boolean.class, "", Options.class, "Master2", Master2);
+ static final OptionDescriptor nestedOption2 = OptionDescriptor.create("NestedOption2", OptionType.Debug, Boolean.class, "", Options.class, "NestedOption2", NestedOption2);
@Test
public void runDefaultTrue() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/TestOptionKey.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/TestOptionKey.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,6 +36,7 @@
import org.graalvm.compiler.options.ModifiableOptionValues;
import org.graalvm.compiler.options.OptionDescriptor;
import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.options.OptionValues;
import org.junit.Assert;
import org.junit.Assume;
@@ -51,7 +52,7 @@
@Test
public void toStringTest() {
- OptionDescriptor.create("MyOption", String.class, "", Options.class, "MyOption", MyOption);
+ OptionDescriptor.create("MyOption", OptionType.Debug, String.class, "", Options.class, "MyOption", MyOption);
assertEquals("MyOption", MyOption.toString());
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.EnumSet;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
public class EnumOptionKey<T extends Enum<T>> extends OptionKey<T> {
final Class<T> enumClass;
@@ -45,11 +45,11 @@
return EnumSet.allOf(enumClass);
}
- Object valueOf(String name) {
+ public Object valueOf(String name) {
try {
return Enum.valueOf(enumClass, name);
} catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("\"" + name + "\" is not a valid option for " + getName() + ". Valid values are " + EnumSet.allOf(enumClass));
+ throw new IllegalArgumentException("\"" + name + "\" is not a valid option for " + getName() + ". Valid values are " + getAllValues());
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,10 +24,10 @@
import java.util.concurrent.atomic.AtomicReference;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
/**
* A context for obtaining values for {@link OptionKey}s that allows for key/value pairs to be
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionDescriptor.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionDescriptor.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,8 @@
public final class OptionDescriptor {
protected final String name;
- protected final Class<?> type;
+ protected final OptionType optionType;
+ protected final Class<?> optionValueType;
protected final String help;
protected final List<String> extraHelp;
protected final OptionKey<?> optionKey;
@@ -42,39 +43,41 @@
private static final String[] NO_EXTRA_HELP = {};
- public static OptionDescriptor create(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionKey<?> option) {
- return create(name, type, help, NO_EXTRA_HELP, declaringClass, fieldName, option);
+ public static OptionDescriptor create(String name, OptionType optionType, Class<?> optionValueType, String help, Class<?> declaringClass, String fieldName, OptionKey<?> option) {
+ return create(name, optionType, optionValueType, help, NO_EXTRA_HELP, declaringClass, fieldName, option);
}
- public static OptionDescriptor create(String name, Class<?> type, String help, String[] extraHelp, Class<?> declaringClass, String fieldName, OptionKey<?> option) {
+ public static OptionDescriptor create(String name, OptionType optionType, Class<?> optionValueType, String help, String[] extraHelp, Class<?> declaringClass, String fieldName,
+ OptionKey<?> option) {
assert option != null : declaringClass + "." + fieldName;
OptionDescriptor result = option.getDescriptor();
if (result == null) {
List<String> extraHelpList = extraHelp == null || extraHelp.length == 0 ? Collections.emptyList() : Collections.unmodifiableList(Arrays.asList(extraHelp));
- result = new OptionDescriptor(name, type, help, extraHelpList, declaringClass, fieldName, option);
+ result = new OptionDescriptor(name, optionType, optionValueType, help, extraHelpList, declaringClass, fieldName, option);
option.setDescriptor(result);
}
- assert result.name.equals(name) && result.type == type && result.declaringClass == declaringClass && result.fieldName.equals(fieldName) && result.optionKey == option;
+ assert result.name.equals(name) && result.optionValueType == optionValueType && result.declaringClass == declaringClass && result.fieldName.equals(fieldName) && result.optionKey == option;
return result;
}
- private OptionDescriptor(String name, Class<?> type, String help, List<String> extraHelp, Class<?> declaringClass, String fieldName, OptionKey<?> optionKey) {
+ private OptionDescriptor(String name, OptionType optionType, Class<?> optionValueType, String help, List<String> extraHelp, Class<?> declaringClass, String fieldName, OptionKey<?> optionKey) {
this.name = name;
- this.type = type;
+ this.optionType = optionType;
+ this.optionValueType = optionValueType;
this.help = help;
this.extraHelp = extraHelp;
this.optionKey = optionKey;
this.declaringClass = declaringClass;
this.fieldName = fieldName;
- assert !type.isPrimitive() : "must used boxed type instead of " + type;
+ assert !optionValueType.isPrimitive() : "must used boxed optionValueType instead of " + optionValueType;
}
/**
* Gets the type of values stored in the option. This will be the boxed type for a primitive
* option.
*/
- public Class<?> getType() {
- return type;
+ public Class<?> getOptionValueType() {
+ return optionValueType;
}
/**
@@ -104,6 +107,13 @@
}
/**
+ * Gets the type of the option.
+ */
+ public OptionType getOptionType() {
+ return optionType;
+ }
+
+ /**
* Gets the boxed option value.
*/
public OptionKey<?> getOptionKey() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.Formatter;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
/**
* A key for an option. The value for an option is obtained from an {@link OptionValues} object.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
import java.util.SortedMap;
import java.util.TreeMap;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
/**
* A context for obtaining values for {@link OptionKey}s.
@@ -126,7 +126,7 @@
/**
* Decodes a value that may be the sentinel value for {@code null} in a map.
*/
- protected static Object decodeNull(Object value) {
+ public static Object decodeNull(Object value) {
return value == NULL ? null : value;
}
@@ -212,7 +212,7 @@
String name = namePrefix + e.getKey();
String assign = containsKey(desc.optionKey) ? ":=" : "=";
- String typeName = desc.getOptionKey() instanceof EnumOptionKey ? "String" : desc.getType().getSimpleName();
+ String typeName = desc.getOptionKey() instanceof EnumOptionKey ? "String" : desc.getOptionValueType().getSimpleName();
String linePrefix = String.format("%s %s %s ", name, assign, value);
int typeStartPos = PROPERTY_LINE_WIDTH - typeName.length();
int linePad = typeStartPos - linePrefix.length();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValuesAccess.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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;
-
-/**
- * Defines a service that supplies values for options. The values supplied may come from a source
- * such as system properties or a command line.
- *
- * This mechanism for obtaining option values must only be used if there is no other more local
- * context from which option values can be obtained.
- */
-public interface OptionValuesAccess {
-
- /**
- * Gets the option values available via this service.
- */
- OptionValues getOptions();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
import java.util.List;
import java.util.ServiceLoader;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.util.CollectionsUtil;
/**
@@ -116,7 +116,7 @@
* @param loader source of the available {@link OptionDescriptors}
* @throws IllegalArgumentException if there's a problem parsing {@code option}
*/
- static void parseOption(String name, Object uncheckedValue, EconomicMap<OptionKey<?>, Object> values, Iterable<OptionDescriptors> loader) {
+ public static void parseOption(String name, Object uncheckedValue, EconomicMap<OptionKey<?>, Object> values, Iterable<OptionDescriptors> loader) {
OptionDescriptor desc = lookup(loader, name);
if (desc == null) {
@@ -132,7 +132,7 @@
throw new IllegalArgumentException(msg.toString());
}
- Class<?> optionType = desc.getType();
+ Class<?> optionType = desc.getOptionValueType();
Object value;
if (!(uncheckedValue instanceof String)) {
if (optionType != uncheckedValue.getClass()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -93,7 +93,7 @@
} else {
continue;
}
- // the lowered address amy already be a replacement
+ // the lowered address may already be a replacement
// in which case we want to use it not delete it!
if (lowered != address) {
// replace original with lowered at this usage only
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -314,7 +314,7 @@
@SuppressWarnings("try")
public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
- try (DebugCloseable position = node.withNodeSourcePosition()) {
+ try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.scope("tryCanonicalize", node)) {
if (customCanonicalizer != null) {
Node canonical = customCanonicalizer.canonicalize(node);
if (performReplacement(node, canonical)) {
@@ -349,6 +349,8 @@
return node.isDeleted();
}
return false;
+ } catch (Throwable throwable) {
+ throw debug.handle(throwable);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,10 +28,10 @@
import java.util.Deque;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,7 @@
import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
@@ -51,6 +52,7 @@
private static final double EPSILON = 1E-6;
@Override
+ @SuppressWarnings("try")
protected void run(StructuredGraph graph) {
for (ShortCircuitOrNode logic : graph.getNodes(ShortCircuitOrNode.TYPE)) {
processBinary(logic);
@@ -58,7 +60,9 @@
assert graph.getNodes(ShortCircuitOrNode.TYPE).isEmpty();
for (NormalizeCompareNode logic : graph.getNodes(NormalizeCompareNode.TYPE)) {
- processNormalizeCompareNode(logic);
+ try (DebugCloseable context = logic.withNodeSourcePosition()) {
+ processNormalizeCompareNode(logic);
+ }
}
graph.setAfterExpandLogic();
}
@@ -84,76 +88,83 @@
normalize.replaceAtUsagesAndDelete(value);
}
+ @SuppressWarnings("try")
private static void processBinary(ShortCircuitOrNode binary) {
while (binary.usages().isNotEmpty()) {
Node usage = binary.usages().first();
- if (usage instanceof ShortCircuitOrNode) {
- processBinary((ShortCircuitOrNode) usage);
- } else if (usage instanceof IfNode) {
- processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, binary.getShortCircuitProbability());
- } else if (usage instanceof ConditionalNode) {
- processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage);
- } else {
- throw GraalError.shouldNotReachHere();
+ try (DebugCloseable nsp = usage.withNodeSourcePosition()) {
+ if (usage instanceof ShortCircuitOrNode) {
+ processBinary((ShortCircuitOrNode) usage);
+ } else if (usage instanceof IfNode) {
+ processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, binary.getShortCircuitProbability());
+ } else if (usage instanceof ConditionalNode) {
+ processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage);
+ } else {
+ throw GraalError.shouldNotReachHere();
+ }
}
}
binary.safeDelete();
}
+ @SuppressWarnings("try")
private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
- /*
- * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into two
- * separate IfNodes: if(X) and if(Y)
- *
- * for computing the probabilities P(X) and P(Y), we use two different approaches. The first
- * one assumes that the shortCircuitProbability and the probability on the IfNode were
- * created with each other in mind. If this assumption does not hold, we fall back to
- * another mechanism for computing the probabilities.
- */
- AbstractBeginNode trueTarget = ifNode.trueSuccessor();
- AbstractBeginNode falseTarget = ifNode.falseSuccessor();
-
- // 1st approach
- // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
- double firstIfTrueProbability = shortCircuitProbability;
- double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability));
- double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability;
-
- if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) {
+ try (DebugCloseable context = ifNode.withNodeSourcePosition()) {
/*
- * 2nd approach
- *
- * the assumption above did not hold, so we either used an artificial probability as
- * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode.
+ * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into
+ * two separate IfNodes: if(X) and if(Y)
*
- * so, we distribute the if's trueSuccessorProbability between the newly generated if
- * nodes according to the shortCircuitProbability. the following invariant is always
- * true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
+ * for computing the probabilities P(X) and P(Y), we use two different approaches. The
+ * first one assumes that the shortCircuitProbability and the probability on the IfNode
+ * were created with each other in mind. If this assumption does not hold, we fall back
+ * to another mechanism for computing the probabilities.
*/
- firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability;
- secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability)));
- }
+ AbstractBeginNode trueTarget = ifNode.trueSuccessor();
+ AbstractBeginNode falseTarget = ifNode.falseSuccessor();
+
+ // 1st approach
+ // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
+ double firstIfTrueProbability = shortCircuitProbability;
+ double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability));
+ double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability;
- ifNode.clearSuccessors();
- Graph graph = ifNode.graph();
- AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
- trueTargetMerge.setNext(trueTarget);
- EndNode firstTrueEnd = graph.add(new EndNode());
- EndNode secondTrueEnd = graph.add(new EndNode());
- trueTargetMerge.addForwardEnd(firstTrueEnd);
- trueTargetMerge.addForwardEnd(secondTrueEnd);
- AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
- AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
- if (yNegated) {
- secondIfTrueProbability = 1.0 - secondIfTrueProbability;
+ if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) {
+ /*
+ * 2nd approach
+ *
+ * the assumption above did not hold, so we either used an artificial probability as
+ * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode.
+ *
+ * so, we distribute the if's trueSuccessorProbability between the newly generated
+ * if nodes according to the shortCircuitProbability. the following invariant is
+ * always true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) *
+ * P(Y))
+ */
+ firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability;
+ secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability)));
+ }
+
+ ifNode.clearSuccessors();
+ Graph graph = ifNode.graph();
+ AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
+ trueTargetMerge.setNext(trueTarget);
+ EndNode firstTrueEnd = graph.add(new EndNode());
+ EndNode secondTrueEnd = graph.add(new EndNode());
+ trueTargetMerge.addForwardEnd(firstTrueEnd);
+ trueTargetMerge.addForwardEnd(secondTrueEnd);
+ AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
+ AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
+ if (yNegated) {
+ secondIfTrueProbability = 1.0 - secondIfTrueProbability;
+ }
+ if (xNegated) {
+ firstIfTrueProbability = 1.0 - firstIfTrueProbability;
+ }
+ AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability)));
+ IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability));
+ ifNode.replaceAtPredecessor(firstIf);
+ ifNode.safeDelete();
}
- if (xNegated) {
- firstIfTrueProbability = 1.0 - firstIfTrueProbability;
- }
- AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability)));
- IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability));
- ifNode.replaceAtPredecessor(firstIf);
- ifNode.safeDelete();
}
private static boolean doubleEquals(double a, double b) {
@@ -169,13 +180,16 @@
return newValue;
}
+ @SuppressWarnings("try")
private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional) {
- ValueNode trueTarget = conditional.trueValue();
- ValueNode falseTarget = conditional.falseValue();
- Graph graph = conditional.graph();
- ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
- ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
- conditional.replaceAndDelete(firstConditional);
+ try (DebugCloseable context = conditional.withNodeSourcePosition()) {
+ ValueNode trueTarget = conditional.trueValue();
+ ValueNode falseTarget = conditional.falseValue();
+ Graph graph = conditional.graph();
+ ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
+ ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
+ conditional.replaceAndDelete(firstConditional);
+ }
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
*/
package org.graalvm.compiler.phases.common;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.FloatStamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,16 +24,16 @@
import static org.graalvm.compiler.graph.Graph.NodeEvent.NODE_ADDED;
import static org.graalvm.compiler.graph.Graph.NodeEvent.ZERO_USAGES;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
@@ -71,7 +71,7 @@
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.LoopInfo;
import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public class FloatingReadPhase extends Phase {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import java.util.List;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -75,7 +75,7 @@
import org.graalvm.compiler.phases.Phase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.DeoptimizationAction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,9 +22,9 @@
*/
package org.graalvm.compiler.phases.common;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.graph.NodeStack;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractDeoptimizeNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,11 +33,11 @@
import java.util.Objects;
import java.util.function.Consumer;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.core.common.GraalOptions;
@@ -45,6 +45,7 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.core.common.util.Util;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.GraalGraphError;
@@ -340,7 +341,13 @@
*/
@SuppressWarnings("try")
public static UnmodifiableEconomicMap<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod) {
- return inline(invoke, inlineGraph, receiverNullCheck, inlineeMethod, "", "");
+ try {
+ return inline(invoke, inlineGraph, receiverNullCheck, inlineeMethod, "reason not specified", "phase not specified");
+ } catch (GraalError ex) {
+ ex.addContext("inlining into", invoke.asNode().graph().method());
+ ex.addContext("inlinee", inlineGraph.method());
+ throw ex;
+ }
}
/**
@@ -423,7 +430,7 @@
try (InliningLog.UpdateScope scope = graph.getInliningLog().openDefaultUpdateScope()) {
duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement);
if (scope != null) {
- graph.getInliningLog().addDecision(invoke, true, reason, phase, duplicates, inlineGraph.getInliningLog());
+ graph.getInliningLog().addDecision(invoke, true, phase, duplicates, inlineGraph.getInliningLog(), reason);
}
}
@@ -491,13 +498,8 @@
* @return the set of nodes to canonicalize
*/
@SuppressWarnings("try")
- public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod) {
- return inlineForCanonicalization(invoke, inlineGraph, receiverNullCheck, inlineeMethod, null);
- }
-
- public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod,
- Consumer<UnmodifiableEconomicMap<Node, Node>> duplicatesConsumer) {
- return inlineForCanonicalization(invoke, inlineGraph, receiverNullCheck, inlineeMethod, duplicatesConsumer, "", "");
+ public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod, String reason, String phase) {
+ return inlineForCanonicalization(invoke, inlineGraph, receiverNullCheck, inlineeMethod, null, reason, phase);
}
@SuppressWarnings("try")
@@ -684,28 +686,42 @@
newNodes.addAll(invokeGraph.getNewNodes(mark));
EconomicMap<NodeSourcePosition, NodeSourcePosition> posMap = EconomicMap.create(Equivalence.DEFAULT);
UnmodifiableMapCursor<Node, Node> cursor = duplicates.getEntries();
+ ResolvedJavaMethod inlineeRoot = null;
while (cursor.advance()) {
- if (!newNodes.contains(cursor.getValue())) {
+ Node value = cursor.getValue();
+ if (!newNodes.contains(value)) {
continue;
}
- NodeSourcePosition pos = cursor.getKey().getNodeSourcePosition();
- if (pos != null) {
- NodeSourcePosition callerPos = posMap.get(pos);
- if (callerPos == null) {
- callerPos = pos.addCaller(invokePos, isSubstitution);
- posMap.put(pos, callerPos);
- }
- cursor.getValue().setNodeSourcePosition(callerPos);
+ if (isSubstitution && invokePos == null) {
+ // There's no caller information so the source position for this node will be
+ // invalid, so it should be cleared.
+ value.clearNodeSourcePosition();
} else {
- if (isSubstitution) {
- /*
- * If no other position is provided at least attribute the substituted node to
- * the original invoke.
- */
- cursor.getValue().setNodeSourcePosition(invokePos);
+ NodeSourcePosition pos = cursor.getKey().getNodeSourcePosition();
+ if (pos != null) {
+ if (inlineeRoot == null) {
+ assert (inlineeRoot = pos.getRootMethod()) != null;
+ } else {
+ assert pos.verifyRootMethod(inlineeRoot);
+ }
+ NodeSourcePosition callerPos = posMap.get(pos);
+ if (callerPos == null) {
+ callerPos = pos.addCaller(invokePos, isSubstitution);
+ posMap.put(pos, callerPos);
+ }
+ value.setNodeSourcePosition(callerPos);
+ } else {
+ if (isSubstitution) {
+ /*
+ * If no other position is provided at least attribute the substituted node
+ * to the original invoke.
+ */
+ value.setNodeSourcePosition(invokePos);
+ }
}
}
}
+ assert invokeGraph.verifySourcePositions();
}
public static void processMonitorId(FrameState stateAfter, MonitorIdNode monitorIdNode) {
@@ -942,37 +958,42 @@
* Gets the receiver for an invoke, adding a guard if necessary to ensure it is non-null, and
* ensuring that the resulting type is compatible with the method being invoked.
*/
+ @SuppressWarnings("try")
public static ValueNode nonNullReceiver(Invoke invoke) {
- MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
- assert !callTarget.isStatic() : callTarget.targetMethod();
- StructuredGraph graph = callTarget.graph();
- ValueNode oldReceiver = callTarget.arguments().get(0);
- ValueNode newReceiver = oldReceiver;
- if (newReceiver.getStackKind() == JavaKind.Object) {
+ try (DebugCloseable position = invoke.asNode().withNodeSourcePosition()) {
+ MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
+ assert !callTarget.isStatic() : callTarget.targetMethod();
+ StructuredGraph graph = callTarget.graph();
+ ValueNode oldReceiver = callTarget.arguments().get(0);
+ ValueNode newReceiver = oldReceiver;
+ if (newReceiver.getStackKind() == JavaKind.Object) {
- if (invoke.getInvokeKind() == InvokeKind.Special) {
- Stamp paramStamp = newReceiver.stamp(NodeView.DEFAULT);
- Stamp stamp = paramStamp.join(StampFactory.object(TypeReference.create(graph.getAssumptions(), callTarget.targetMethod().getDeclaringClass())));
- if (!stamp.equals(paramStamp)) {
- // The verifier and previous optimizations guarantee unconditionally that the
- // receiver is at least of the type of the method holder for a special invoke.
- newReceiver = graph.unique(new PiNode(newReceiver, stamp));
+ if (invoke.getInvokeKind() == InvokeKind.Special) {
+ Stamp paramStamp = newReceiver.stamp(NodeView.DEFAULT);
+ Stamp stamp = paramStamp.join(StampFactory.object(TypeReference.create(graph.getAssumptions(), callTarget.targetMethod().getDeclaringClass())));
+ if (!stamp.equals(paramStamp)) {
+ // The verifier and previous optimizations guarantee unconditionally that
+ // the
+ // receiver is at least of the type of the method holder for a special
+ // invoke.
+ newReceiver = graph.unique(new PiNode(newReceiver, stamp));
+ }
+ }
+
+ if (!StampTool.isPointerNonNull(newReceiver)) {
+ LogicNode condition = graph.unique(IsNullNode.create(newReceiver));
+ FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true));
+ PiNode nonNullReceiver = graph.unique(new PiNode(newReceiver, StampFactory.objectNonNull(), fixedGuard));
+ graph.addBeforeFixed(invoke.asNode(), fixedGuard);
+ newReceiver = nonNullReceiver;
}
}
- if (!StampTool.isPointerNonNull(newReceiver)) {
- LogicNode condition = graph.unique(IsNullNode.create(newReceiver));
- FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true));
- PiNode nonNullReceiver = graph.unique(new PiNode(newReceiver, StampFactory.objectNonNull(), fixedGuard));
- graph.addBeforeFixed(invoke.asNode(), fixedGuard);
- newReceiver = nonNullReceiver;
+ if (newReceiver != oldReceiver) {
+ callTarget.replaceFirstInput(oldReceiver, newReceiver);
}
+ return newReceiver;
}
-
- if (newReceiver != oldReceiver) {
- callTarget.replaceFirstInput(oldReceiver, newReceiver);
- }
- return newReceiver;
}
public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target, int invokeBci) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -54,10 +54,10 @@
}
@SuppressWarnings("try")
- protected static EconomicSet<Node> inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, boolean receiverNullCheck) {
+ protected static EconomicSet<Node> inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, boolean receiverNullCheck, String reason) {
assert inlineable instanceof InlineableGraph;
StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph();
- return InliningUtil.inlineForCanonicalization(invoke, calleeGraph, receiverNullCheck, concrete);
+ return InliningUtil.inlineForCanonicalization(invoke, calleeGraph, receiverNullCheck, concrete, reason, "InliningPhase");
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.Invoke;
@@ -46,9 +46,9 @@
}
@Override
- public EconomicSet<Node> inline(Providers providers) {
+ public EconomicSet<Node> inline(Providers providers, String reason) {
takenAssumption.recordTo(invoke.asNode().graph().getAssumptions());
- return super.inline(providers);
+ return super.inline(providers, reason);
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
@@ -51,8 +51,8 @@
}
@Override
- public EconomicSet<Node> inline(Providers providers) {
- return inline(invoke, concrete, inlineableElement, !suppressNullCheck);
+ public EconomicSet<Node> inline(Providers providers, String reason) {
+ return inline(invoke, concrete, inlineableElement, !suppressNullCheck, reason);
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -75,7 +75,7 @@
*
* @return a collection of nodes that need to be canonicalized after the inlining
*/
- EconomicSet<Node> inline(Providers providers);
+ EconomicSet<Node> inline(Providers providers, String reason);
/**
* Try to make the call static bindable to avoid interface and virtual method calls.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.AbstractBeginNode;
@@ -156,11 +156,11 @@
}
@Override
- public EconomicSet<Node> inline(Providers providers) {
+ public EconomicSet<Node> inline(Providers providers, String reason) {
if (hasSingleMethod()) {
- return inlineSingleMethod(graph(), providers.getStampProvider(), providers.getConstantReflection());
+ return inlineSingleMethod(graph(), providers.getStampProvider(), providers.getConstantReflection(), reason);
} else {
- return inlineMultipleMethods(graph(), providers);
+ return inlineMultipleMethods(graph(), providers, reason);
}
}
@@ -182,7 +182,7 @@
return notRecordedTypeProbability > 0;
}
- private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, Providers providers) {
+ private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, Providers providers, String reason) {
int numberOfMethods = concretes.size();
FixedNode continuation = invoke.next();
@@ -277,7 +277,7 @@
// do the actual inlining for every invoke
for (int i = 0; i < numberOfMethods; i++) {
Invoke invokeForInlining = (Invoke) successors[i].next();
- canonicalizeNodes.addAll(doInline(i, invokeForInlining));
+ canonicalizeNodes.addAll(doInline(i, invokeForInlining, reason));
}
if (returnValuePhi != null) {
canonicalizeNodes.add(returnValuePhi);
@@ -285,8 +285,8 @@
return canonicalizeNodes;
}
- protected EconomicSet<Node> doInline(int index, Invoke invokeForInlining) {
- return inline(invokeForInlining, methodAt(index), inlineableElementAt(index), false);
+ protected EconomicSet<Node> doInline(int index, Invoke invokeForInlining, String reason) {
+ return inline(invokeForInlining, methodAt(index), inlineableElementAt(index), false, reason);
}
private int getTypeCount(int concreteMethodIndex) {
@@ -322,7 +322,7 @@
return result;
}
- private EconomicSet<Node> inlineSingleMethod(StructuredGraph graph, StampProvider stampProvider, ConstantReflectionProvider constantReflection) {
+ private EconomicSet<Node> inlineSingleMethod(StructuredGraph graph, StampProvider stampProvider, ConstantReflectionProvider constantReflection, String reason) {
assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
@@ -333,7 +333,7 @@
calleeEntryNode.setNext(invoke.asNode());
- return inline(invoke, methodAt(0), inlineableElementAt(0), false);
+ return inline(invoke, methodAt(0), inlineableElementAt(0), false, reason);
}
private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, StampProvider stampProvider,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,9 @@
*/
package org.graalvm.compiler.phases.common.inlining.info;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.common.calc.CanonicalCondition;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.ConstantNode;
@@ -98,9 +99,9 @@
}
@Override
- public EconomicSet<Node> inline(Providers providers) {
+ public EconomicSet<Node> inline(Providers providers, String reason) {
createGuard(graph(), providers);
- return inline(invoke, concrete, inlineableElement, false);
+ return inline(invoke, concrete, inlineableElement, false, reason);
}
@Override
@@ -109,19 +110,22 @@
InliningUtil.replaceInvokeCallTarget(invoke, graph(), InvokeKind.Special, concrete);
}
+ @SuppressWarnings("try")
private void createGuard(StructuredGraph graph, Providers providers) {
- ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
- LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));
- ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(NodeView.DEFAULT), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph);
+ try (DebugCloseable context = invoke.asNode().withNodeSourcePosition()) {
+ ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
+ LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));
+ ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(NodeView.DEFAULT), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph);
- LogicNode typeCheck = CompareNode.createCompareNode(graph, CanonicalCondition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT);
- FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
- assert invoke.predecessor() != null;
+ LogicNode typeCheck = CompareNode.createCompareNode(graph, CanonicalCondition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT);
+ FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
+ assert invoke.predecessor() != null;
- ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true);
- invoke.callTarget().replaceFirstInput(nonNullReceiver, anchoredReceiver);
+ ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true);
+ invoke.callTarget().replaceFirstInput(nonNullReceiver, anchoredReceiver);
- graph.addBeforeFixed(invoke.asNode(), guard);
+ graph.addBeforeFixed(invoke.asNode(), guard);
+ }
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,6 +27,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize;
import static org.graalvm.compiler.core.common.GraalOptions.SmallCompiledLowLevelGraphSize;
+import static org.graalvm.compiler.core.common.GraalOptions.TraceInlining;
import static org.graalvm.compiler.core.common.GraalOptions.TrivialInliningSize;
import java.util.Map;
@@ -61,8 +62,8 @@
}
@Override
- public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
-
+ public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+ final boolean isTracing = TraceInlining.getValue(replacements.getOptions());
final InlineInfo info = invocation.callee();
OptionValues options = info.graph().getOptions();
final double probability = invocation.probability();
@@ -70,17 +71,17 @@
if (InlineEverything.getValue(options)) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything");
}
if (isIntrinsic(replacements, info)) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "intrinsic");
}
if (info.shouldInline()) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "forced inlining");
}
double inliningBonus = getInliningBonus(info);
@@ -90,12 +91,13 @@
if (SmallCompiledLowLevelGraphSize.getValue(options) > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue(options) * inliningBonus) {
InliningUtil.traceNotInlinedMethod(info, inliningDepth, "too large previous low-level graph (low-level-nodes: %d, relevance=%f, probability=%f, bonus=%f, nodes=%d)", lowLevelGraphSize,
relevance, probability, inliningBonus, nodes);
- return false;
+ return InliningPolicy.Decision.NO.withReason(isTracing, "too large previous low-level graph (low-level-nodes: %d, relevance=%f, probability=%f, bonus=%f, nodes=%d)", lowLevelGraphSize,
+ relevance, probability, inliningBonus, nodes);
}
if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
}
/*
@@ -108,17 +110,19 @@
if (LimitInlinedInvokes.getValue(options) > 0 && fullyProcessed && invokes > LimitInlinedInvokes.getValue(options) * inliningBonus) {
InliningUtil.traceNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes, relevance,
probability, inliningBonus, nodes);
- return false;
+ return InliningPolicy.Decision.NO.withReason(isTracing, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes, relevance,
+ probability, inliningBonus, nodes);
}
double maximumNodes = computeMaximumSize(relevance, (int) (MaximumInliningSize.getValue(options) * inliningBonus));
if (nodes <= maximumNodes) {
InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
nodes, maximumNodes);
- return true;
+ return InliningPolicy.Decision.YES.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
+ nodes, maximumNodes);
}
InliningUtil.traceNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
- return false;
+ return InliningPolicy.Decision.NO.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
+import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.Replacements;
@@ -41,7 +42,7 @@
}
@Override
- public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
- return true;
+ public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+ return Decision.YES.withReason(GraalOptions.TraceInlining.getValue(replacements.getOptions()), "inline everything");
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.phases.common.inlining.policy;
+import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.nodes.CallTargetNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.Replacements;
@@ -35,14 +36,15 @@
public final class InlineMethodSubstitutionsPolicy extends InlineEverythingPolicy {
@Override
- public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+ public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+ final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions());
CallTargetNode callTarget = invocation.callee().invoke().callTarget();
if (callTarget instanceof MethodCallTargetNode) {
ResolvedJavaMethod calleeMethod = ((MethodCallTargetNode) callTarget).targetMethod();
if (replacements.hasSubstitution(calleeMethod, invocation.callee().invoke().bci())) {
- return true;
+ return Decision.YES.withReason(isTracing, "has a method subtitution");
}
}
- return false;
+ return Decision.NO.withReason(isTracing, "does not have a method substitution");
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,36 @@
import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
public interface InliningPolicy {
+ class Decision {
+ public static final Decision YES = new Decision(true, "(unknown reason)");
+ public static final Decision NO = new Decision(false, "(unknown reason)");
+
+ private final boolean shouldInline;
+ private final String reason;
+
+ private Decision(boolean shouldInline, String reason) {
+ this.shouldInline = shouldInline;
+ this.reason = reason;
+ }
+
+ public boolean shouldInline() {
+ return shouldInline;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public Decision withReason(boolean isTracing, String newReason, Object... args) {
+ if (isTracing) {
+ return new Decision(shouldInline, String.format(newReason, args));
+ } else {
+ return this;
+ }
+ }
+ }
boolean continueInlining(StructuredGraph graph);
- boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed);
+ Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.util.LinkedList;
import java.util.function.ToDoubleFunction;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.ParameterNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
import java.util.ArrayList;
import java.util.function.ToDoubleFunction;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeWorkList;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java Thu Apr 26 17:59:02 2018 +0200
@@ -34,8 +34,8 @@
import java.util.LinkedList;
import java.util.List;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
@@ -167,6 +167,7 @@
return true;
} else {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), method, failureMessage);
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, failureMessage);
return false;
}
}
@@ -258,12 +259,14 @@
JavaTypeProfile typeProfile = ((MethodCallTargetNode) invoke.callTarget()).getProfile();
if (typeProfile == null) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no type profile exists");
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "no type profile exists");
return null;
}
JavaTypeProfile.ProfiledType[] ptypes = typeProfile.getTypes();
if (ptypes == null || ptypes.length <= 0) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no types in profile");
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "no types in profile");
return null;
}
ResolvedJavaType contextType = invoke.getContextType();
@@ -273,6 +276,7 @@
if (ptypes.length == 1 && notRecordedTypeProbability == 0) {
if (!optimisticOpts.inlineMonomorphicCalls(options)) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining monomorphic calls is disabled");
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "inlining monomorphic calls is disabled");
return null;
}
@@ -288,6 +292,7 @@
if (!optimisticOpts.inlinePolymorphicCalls(options) && notRecordedTypeProbability == 0) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining polymorphic calls is disabled (%d types)", ptypes.length);
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "inlining polymorphic calls is disabled (%d types)", ptypes.length);
return null;
}
if (!optimisticOpts.inlineMegamorphicCalls(options) && notRecordedTypeProbability > 0) {
@@ -295,6 +300,8 @@
// the number of types is lower than what can be recorded in a type profile
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.length,
notRecordedTypeProbability * 100);
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null,
+ "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.length, notRecordedTypeProbability);
return null;
}
@@ -305,6 +312,7 @@
ResolvedJavaMethod concrete = ptypes[i].getType().resolveConcreteMethod(targetMethod, contextType);
if (concrete == null) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "could not resolve method");
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "could not resolve method");
return null;
}
int index = concreteMethods.indexOf(concrete);
@@ -333,6 +341,8 @@
// No method left that is worth inlining.
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no methods remaining after filtering less frequent methods (%d methods previously)",
concreteMethods.size());
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null,
+ "no methods remaining after filtering less frequent methods (%d methods previously)", concreteMethods.size());
return null;
}
@@ -342,6 +352,7 @@
if (concreteMethods.size() > maxMethodPerInlining) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining);
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "polymorphic call with more than %d target methods", maxMethodPerInlining);
return null;
}
@@ -363,12 +374,16 @@
if (usedTypes.isEmpty()) {
// No type left that is worth checking for.
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no types remaining after filtering less frequent types (%d types previously)", ptypes.length);
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "no types remaining after filtering less frequent types (%d types previously)",
+ ptypes.length);
return null;
}
for (ResolvedJavaMethod concrete : concreteMethods) {
if (!checkTargetConditions(invoke, concrete)) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined");
+ invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null,
+ "it is a polymorphic method call and at least one invoked method cannot be inlined");
return null;
}
}
@@ -393,14 +408,14 @@
}
@SuppressWarnings("try")
- private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation) {
+ private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation, String reason) {
StructuredGraph callerGraph = callerCallsiteHolder.graph();
InlineInfo calleeInfo = calleeInvocation.callee();
try {
try (DebugContext.Scope scope = debug.scope("doInline", callerGraph)) {
EconomicSet<Node> canonicalizedNodes = EconomicSet.create(Equivalence.IDENTITY);
canonicalizedNodes.addAll(calleeInfo.invoke().asNode().usages());
- EconomicSet<Node> parameterUsages = calleeInfo.inline(new Providers(context));
+ EconomicSet<Node> parameterUsages = calleeInfo.inline(new Providers(context), reason);
canonicalizedNodes.addAll(parameterUsages);
counterInliningRuns.increment(debug);
debug.dump(DebugContext.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo);
@@ -449,8 +464,9 @@
assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke());
counterInliningConsidered.increment(debug);
- if (inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true)) {
- doInline(callerCallsiteHolder, calleeInvocation);
+ InliningPolicy.Decision decision = inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true);
+ if (decision.shouldInline()) {
+ doInline(callerCallsiteHolder, calleeInvocation, decision.getReason());
return true;
}
@@ -483,7 +499,7 @@
* <p>
* The {@link InlineInfo} used to get things rolling is kept around in the
* {@link MethodInvocation}, it will be needed in case of inlining, see
- * {@link InlineInfo#inline(Providers)}
+ * {@link InlineInfo#inline(Providers, String)}
* </p>
*/
private void processNextInvoke() {
@@ -709,7 +725,7 @@
final MethodInvocation currentInvocation = currentInvocation();
- final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, inliningDepth(), false));
+ final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, inliningDepth(), false).shouldInline());
if (backtrack) {
int remainingGraphs = currentInvocation.totalGraphs() - currentInvocation.processedGraphs();
assert remainingGraphs > 0;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.util.HashSet;
import java.util.Set;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.graph.Graph.NodeEvent;
import org.graalvm.compiler.graph.Graph.NodeEventListener;
import org.graalvm.compiler.graph.Node;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.util.function.ToDoubleFunction;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
import java.util.Deque;
import java.util.Set;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeBitMap;
import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
import java.util.List;
import java.util.function.Predicate;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.RetryableBailoutException;
import org.graalvm.compiler.core.common.cfg.Loop;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,9 +28,9 @@
import java.util.Iterator;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
import java.util.Deque;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeBitMap;
import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,8 +24,8 @@
import java.util.List;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.DebugContext;
@@ -42,7 +42,7 @@
import org.graalvm.compiler.nodes.memory.MemoryPhiNode;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public final class MemoryScheduleVerification extends BlockIteratorClosure<EconomicSet<FloatingReadNode>> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.phases.schedule;
-import static org.graalvm.collections.Equivalence.IDENTITY;
+import static jdk.internal.vm.compiler.collections.Equivalence.IDENTITY;
import static org.graalvm.compiler.core.common.GraalOptions.GuardPriorities;
import static org.graalvm.compiler.core.common.GraalOptions.OptScheduleOutOfLoops;
import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates;
@@ -38,7 +38,7 @@
import java.util.TreeSet;
import java.util.function.Function;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.common.SuppressFBWarnings;
import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
import org.graalvm.compiler.core.common.cfg.BlockMap;
@@ -83,7 +83,7 @@
import org.graalvm.compiler.nodes.spi.ValueProxy;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.Phase;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public final class SchedulePhase extends Phase {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/Suites.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/Suites.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,10 @@
*/
package org.graalvm.compiler.phases.tiers;
+import org.graalvm.compiler.lir.alloc.RegisterAllocationPhase;
+import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
+import org.graalvm.compiler.lir.phases.LIRPhase;
+import org.graalvm.compiler.lir.phases.LIRPhaseSuite;
import org.graalvm.compiler.lir.phases.LIRSuites;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.PhaseSuite;
@@ -56,7 +60,25 @@
}
public static LIRSuites createLIRSuites(CompilerConfiguration config, OptionValues options) {
- return new LIRSuites(config.createPreAllocationOptimizationStage(options), config.createAllocationStage(options), config.createPostAllocationOptimizationStage(options));
+ LIRPhaseSuite<AllocationContext> allocationStage = config.createAllocationStage(options);
+ assert verifyAllocationStage(allocationStage);
+ return new LIRSuites(config.createPreAllocationOptimizationStage(options), allocationStage, config.createPostAllocationOptimizationStage(options));
+ }
+
+ private static boolean verifyAllocationStage(LIRPhaseSuite<AllocationContext> allocationStage) {
+ boolean allocationPhase = false;
+ for (LIRPhase<?> phase : allocationStage.getPhases()) {
+ if (phase instanceof RegisterAllocationPhase) {
+ if (allocationPhase) {
+ assert false : "More than one register allocation phase";
+ return false;
+ }
+ allocationPhase = true;
+ }
+
+ }
+ assert allocationPhase : "No register allocation phase";
+ return allocationPhase;
}
public boolean isImmutable() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.GraalGraphError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyCallerSensitiveMethods.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyCallerSensitiveMethods.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.phases.verify;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import java.lang.annotation.Annotation;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,9 @@
import static org.graalvm.compiler.graph.Edges.Type.Successors;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -72,17 +75,26 @@
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.Signature;
+import org.graalvm.graphio.GraphLocations;
public class BinaryGraphPrinter implements
GraphStructure<BinaryGraphPrinter.GraphInfo, Node, NodeClass<?>, Edges>,
GraphBlocks<BinaryGraphPrinter.GraphInfo, Block, Node>,
GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition>,
+ GraphLocations<ResolvedJavaMethod, NodeSourcePosition, SourceLanguagePosition>,
GraphTypes, GraphPrinter {
private final SnippetReflectionProvider snippetReflection;
private final GraphOutput<BinaryGraphPrinter.GraphInfo, ResolvedJavaMethod> output;
public BinaryGraphPrinter(DebugContext ctx, SnippetReflectionProvider snippetReflection) throws IOException {
- this.output = ctx.buildOutput(GraphOutput.newBuilder(this).protocolVersion(5, 0).blocks(this).elements(this).types(this));
+ // @formatter:off
+ this.output = ctx.buildOutput(GraphOutput.newBuilder(this).
+ protocolVersion(6, 0).
+ blocks(this).
+ elementsAndLocations(this, this).
+ types(this)
+ );
+ // @formatter:on
this.snippetReflection = snippetReflection;
}
@@ -266,17 +278,6 @@
}
props.put("category", "floating");
}
- if (node.getNodeSourcePosition() != null) {
- NodeSourcePosition pos = node.getNodeSourcePosition();
- while (pos != null) {
- SourceLanguagePosition cur = pos.getSourceLanauage();
- if (cur != null) {
- cur.addSourceInformation(props);
- break;
- }
- pos = pos.getCaller();
- }
- }
if (getSnippetReflectionProvider() != null) {
for (Map.Entry<String, Object> prop : props.entrySet()) {
if (prop.getValue() instanceof JavaConstantFormattable) {
@@ -502,6 +503,85 @@
return method.asStackTraceElement(bci);
}
+ @Override
+ public Iterable<SourceLanguagePosition> methodLocation(ResolvedJavaMethod method, int bci, NodeSourcePosition pos) {
+ StackTraceElement e = methodStackTraceElement(method, bci, pos);
+ class JavaSourcePosition implements SourceLanguagePosition {
+
+ @Override
+ public String toShortString() {
+ return e.toString();
+ }
+
+ @Override
+ public int getOffsetEnd() {
+ return -1;
+ }
+
+ @Override
+ public int getOffsetStart() {
+ return -1;
+ }
+
+ @Override
+ public int getLineNumber() {
+ return e.getLineNumber();
+ }
+
+ @Override
+ public URI getURI() {
+ String path = e.getFileName();
+ try {
+ return path == null ? null : new URI(null, null, path, null);
+ } catch (URISyntaxException ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ @Override
+ public String getLanguage() {
+ return "Java";
+ }
+ }
+
+ List<SourceLanguagePosition> arr = new ArrayList<>();
+ arr.add(new JavaSourcePosition());
+ NodeSourcePosition at = pos;
+ while (at != null) {
+ SourceLanguagePosition cur = at.getSourceLanguage();
+ if (cur != null) {
+ arr.add(cur);
+ }
+ at = at.getCaller();
+ }
+ return arr;
+ }
+
+ @Override
+ public String locationLanguage(SourceLanguagePosition location) {
+ return location.getLanguage();
+ }
+
+ @Override
+ public URI locationURI(SourceLanguagePosition location) {
+ return location.getURI();
+ }
+
+ @Override
+ public int locationLineNumber(SourceLanguagePosition location) {
+ return location.getLineNumber();
+ }
+
+ @Override
+ public int locationOffsetStart(SourceLanguagePosition location) {
+ return location.getOffsetStart();
+ }
+
+ @Override
+ public int locationOffsetEnd(SourceLanguagePosition location) {
+ return location.getOffsetEnd();
+ }
+
static final class GraphInfo {
final DebugContext debug;
final Graph graph;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
import java.util.Map;
import java.util.TreeMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.core.common.alloc.Trace;
@@ -116,38 +116,38 @@
}
private void printBlock(BciBlockMapping.BciBlock block) {
- out.print("name \"B").print(block.startBci).println('"');
- out.print("from_bci ").println(block.startBci);
- out.print("to_bci ").println(block.endBci);
+ out.print("name \"B").print(block.getStartBci()).println('"');
+ out.print("from_bci ").println(block.getStartBci());
+ out.print("to_bci ").println(block.getEndBci());
out.println("predecessors ");
out.print("successors ");
for (BciBlockMapping.BciBlock succ : block.getSuccessors()) {
- if (!succ.isExceptionEntry) {
- out.print("\"B").print(succ.startBci).print("\" ");
+ if (!succ.isExceptionEntry()) {
+ out.print("\"B").print(succ.getStartBci()).print("\" ");
}
}
out.println();
out.print("xhandlers");
for (BciBlockMapping.BciBlock succ : block.getSuccessors()) {
- if (succ.isExceptionEntry) {
- out.print("\"B").print(succ.startBci).print("\" ");
+ if (succ.isExceptionEntry()) {
+ out.print("\"B").print(succ.getStartBci()).print("\" ");
}
}
out.println();
out.print("flags ");
- if (block.isExceptionEntry) {
+ if (block.isExceptionEntry()) {
out.print("\"ex\" ");
}
- if (block.isLoopHeader) {
+ if (block.isLoopHeader()) {
out.print("\"plh\" ");
}
out.println();
- out.print("loop_depth ").println(Long.bitCount(block.loops));
+ out.print("loop_depth ").println(Long.bitCount(block.getLoops()));
}
private NodeMap<Block> latestScheduling;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,15 +37,13 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.util.JavaConstantFormatter;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MetaUtil;
import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.runtime.JVMCI;
-import jdk.vm.ci.services.Services;
interface GraphPrinter extends Closeable, JavaConstantFormatter {
@@ -72,16 +70,6 @@
void close();
/**
- * A JVMCI package dynamically exported to trusted modules.
- */
- String JVMCI_RUNTIME_PACKAGE = JVMCI.class.getPackage().getName();
-
- /**
- * {@code jdk.vm.ci} module.
- */
- Object JVMCI_MODULE = JDK9Method.JAVA_SPECIFICATION_VERSION < 9 ? null : JDK9Method.getModule(Services.class);
-
- /**
* Classes whose {@link #toString()} method does not run any untrusted code.
*/
List<Class<?>> TRUSTED_CLASSES = Arrays.asList(
@@ -105,17 +93,8 @@
if (TRUSTED_CLASSES.contains(c)) {
return true;
}
- if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) {
- if (c.getClassLoader() == Services.class.getClassLoader()) {
- // Loaded by the JVMCI class loader
- return true;
- }
- } else {
- Object module = JDK9Method.getModule(c);
- if (JVMCI_MODULE == module || JDK9Method.isOpenTo(JVMCI_MODULE, JVMCI_RUNTIME_PACKAGE, module)) {
- // Can access non-statically-exported package in JVMCI
- return true;
- }
+ if (GraalServices.isToStringTrusted(c)) {
+ return true;
}
if (c.getClassLoader() == GraphPrinter.class.getClassLoader()) {
return true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java Thu Apr 26 17:59:02 2018 +0200
@@ -45,6 +45,7 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.contract.NodeCostUtil;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -86,11 +87,11 @@
}
private static String jvmArguments() {
- try {
- return String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
- } catch (LinkageError err) {
- return "unknown";
+ List<String> inputArguments = GraalServices.getInputArguments();
+ if (inputArguments != null) {
+ return String.join(" ", inputArguments);
}
+ return "unknown";
}
private void ensureInitialized(DebugContext ctx, Graph graph) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,6 +28,7 @@
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.GraalServices.JAVA_SPECIFICATION_VERSION;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.nodes.ValueNode;
@@ -53,6 +54,9 @@
registerIntegerLongPlugins(invocationPlugins, AArch64IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider);
registerIntegerLongPlugins(invocationPlugins, AArch64LongSubstitutions.class, JavaKind.Long, bytecodeProvider);
registerMathPlugins(invocationPlugins);
+ registerStringLatin1Plugins(invocationPlugins, bytecodeProvider);
+ registerStringUTF16Plugins(invocationPlugins, bytecodeProvider);
+
}
});
}
@@ -114,4 +118,23 @@
}
});
}
+
+ private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
+ if (JAVA_SPECIFICATION_VERSION >= 9) {
+ Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
+ r.setAllowOverwrite(true);
+ r.registerMethodSubstitution(AArch64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
+ r.registerMethodSubstitution(AArch64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
+ }
+ }
+
+ private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
+ if (JAVA_SPECIFICATION_VERSION >= 9) {
+ Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
+ r.setAllowOverwrite(true);
+ r.registerMethodSubstitution(AArch64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
+ r.registerMethodSubstitution(AArch64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
+ }
+ }
+
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadNode.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, 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.replacements.aarch64;
-
-import jdk.vm.ci.aarch64.AArch64Kind;
-import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator;
-import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator;
-import org.graalvm.compiler.core.common.type.IntegerStamp;
-import org.graalvm.compiler.core.common.type.Stamp;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.FrameState;
-import org.graalvm.compiler.nodes.NodeView;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.calc.SignExtendNode;
-import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
-import org.graalvm.compiler.nodes.extended.GuardingNode;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
-
-/**
- * AArch64-specific subclass of ReadNode that knows how to merge ZeroExtend and SignExtend into the
- * read.
- */
-
-@NodeInfo
-public class AArch64ReadNode extends ReadNode {
- public static final NodeClass<AArch64ReadNode> TYPE = NodeClass.create(AArch64ReadNode.class);
- private final IntegerStamp accessStamp;
- private final boolean isSigned;
-
- public AArch64ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
- FrameState stateBefore, IntegerStamp accessStamp, boolean isSigned) {
- super(TYPE, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
- this.accessStamp = accessStamp;
- this.isSigned = isSigned;
- }
-
- @Override
- public void generate(NodeLIRBuilderTool gen) {
- AArch64LIRGenerator lirgen = (AArch64LIRGenerator) gen.getLIRGeneratorTool();
- AArch64ArithmeticLIRGenerator arithgen = (AArch64ArithmeticLIRGenerator) lirgen.getArithmetic();
- AArch64Kind readKind = (AArch64Kind) lirgen.getLIRKind(accessStamp).getPlatformKind();
- int resultBits = ((IntegerStamp) stamp(NodeView.DEFAULT)).getBits();
- gen.setResult(this, arithgen.emitExtendMemory(isSigned, readKind, resultBits, (AArch64AddressValue) gen.operand(getAddress()), gen.state(this)));
- }
-
- /**
- * replace a ReadNode with an AArch64-specific variant which knows how to merge a downstream
- * zero or sign extend into the read operation.
- *
- * @param readNode
- */
- public static void replace(ReadNode readNode) {
- assert readNode.getUsageCount() == 1;
- assert readNode.getUsageAt(0) instanceof ZeroExtendNode || readNode.getUsageAt(0) instanceof SignExtendNode;
-
- ValueNode usage = (ValueNode) readNode.getUsageAt(0);
- boolean isSigned = usage instanceof SignExtendNode;
- IntegerStamp accessStamp = ((IntegerStamp) readNode.getAccessStamp());
-
- AddressNode address = readNode.getAddress();
- LocationIdentity location = readNode.getLocationIdentity();
- Stamp stamp = usage.stamp(NodeView.DEFAULT);
- GuardingNode guard = readNode.getGuard();
- BarrierType barrierType = readNode.getBarrierType();
- boolean nullCheck = readNode.getNullCheck();
- FrameState stateBefore = readNode.stateBefore();
- AArch64ReadNode clone = new AArch64ReadNode(address, location, stamp, guard, barrierType, nullCheck, stateBefore, accessStamp, isSigned);
- StructuredGraph graph = readNode.graph();
- graph.add(clone);
- // splice out the extend node
- usage.replaceAtUsagesAndDelete(readNode);
- // swap the clone for the read
- graph.replaceFixedWithFixed(readNode, clone);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadReplacementPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, 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.replacements.aarch64;
-
-import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.calc.SignExtendNode;
-import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.phases.Phase;
-
-/**
- * AArch64-specific phase which substitutes certain read nodes with arch-specific variants in order
- * to allow merging of zero and sign extension into the read operation.
- */
-
-public class AArch64ReadReplacementPhase extends Phase {
- @Override
- protected void run(StructuredGraph graph) {
- for (Node node : graph.getNodes()) {
- // don't process nodes we just added
- if (node instanceof AArch64ReadNode) {
- continue;
- }
- if (node instanceof ReadNode) {
- ReadNode readNode = (ReadNode) node;
- if (readNode.getUsageCount() == 1) {
- Node usage = readNode.getUsageAt(0);
- if (usage instanceof ZeroExtendNode || usage instanceof SignExtendNode) {
- AArch64ReadNode.replace(readNode);
- }
- }
- }
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64StringLatin1Substitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.aarch64;
+
+import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
+
+import jdk.vm.ci.meta.JavaKind;
+
+// JaCoCo Exclude
+
+/**
+ * Substitutions for {@code java.lang.StringLatin1} methods.
+ *
+ * Since JDK 9.
+ */
+@ClassSubstitution(className = "java.lang.StringLatin1", optional = true)
+public class AArch64StringLatin1Substitutions {
+
+ /**
+ * @param value is byte[]
+ * @param other is char[]
+ */
+ @MethodSubstitution
+ public static int compareTo(byte[] value, byte[] other) {
+ return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Byte, JavaKind.Byte);
+ }
+
+ /**
+ * @param value is byte[]
+ * @param other is char[]
+ */
+ @MethodSubstitution
+ public static int compareToUTF16(byte[] value, byte[] other) {
+ return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Byte, JavaKind.Char);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64StringUTF16Substitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.aarch64;
+
+import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
+
+import jdk.vm.ci.meta.JavaKind;
+
+// JaCoCo Exclude
+
+/**
+ * Substitutions for {@code java.lang.StringUTF16} methods.
+ *
+ * Since JDK 9.
+ */
+@ClassSubstitution(className = "java.lang.StringUTF16", optional = true)
+public class AArch64StringUTF16Substitutions {
+
+ /**
+ * @param value is char[]
+ * @param other is char[]
+ */
+ @MethodSubstitution
+ public static int compareTo(byte[] value, byte[] other) {
+ return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Char, JavaKind.Char);
+ }
+
+ /**
+ * @param value is char[]
+ * @param other is byte[]
+ */
+ @MethodSubstitution
+ public static int compareToLatin1(byte[] value, byte[] other) {
+ /*
+ * Swapping array arguments because intrinsic expects order to be byte[]/char[] but kind
+ * arguments stay in original order.
+ */
+ return ArrayCompareToNode.compareTo(other, value, other.length, value.length, JavaKind.Char, JavaKind.Byte);
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,8 +29,8 @@
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.JDK9Method.JAVA_SPECIFICATION_VERSION;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.JAVA_SPECIFICATION_VERSION;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import java.util.Arrays;
@@ -57,7 +57,7 @@
import org.graalvm.compiler.replacements.nodes.BitCountNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
@@ -194,8 +194,7 @@
r.registerMethodSubstitution(AMD64StringSubstitutions.class, "indexOf", char[].class, int.class,
int.class, char[].class, int.class, int.class, int.class);
}
- // r.registerMethodSubstitution(AMD64StringSubstitutions.class, "compareTo",
- // Receiver.class, String.class);
+ r.registerMethodSubstitution(AMD64StringSubstitutions.class, "compareTo", Receiver.class, String.class);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringIndexOfNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringIndexOfNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,8 +38,8 @@
import org.graalvm.compiler.nodes.memory.MemoryNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
import org.graalvm.compiler.replacements.StringSubstitutions;
import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.Pointer;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,12 +22,20 @@
*/
package org.graalvm.compiler.replacements.test;
+import static org.graalvm.compiler.core.common.GraalOptions.RemoveNeverExecutedCode;
+import static org.graalvm.compiler.core.common.GraalOptions.UseExceptionProbability;
+import static org.graalvm.compiler.core.common.GraalOptions.UseTypeCheckHints;
+
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.phases.HighTier;
import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.options.OptionValues;
+import org.junit.Ignore;
import org.junit.Test;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
public class NestedExceptionHandlerTest extends GraalCompilerTest {
@BytecodeParserNeverInline(invokeWithException = true)
@@ -63,4 +71,67 @@
test(new OptionValues(getInitialOptions(), HighTier.Options.Inline, false), "nestedExceptionHandler");
}
+ @SuppressWarnings("try")
+ public static String snippet1() {
+ try {
+ synchronized (String.class) {
+ try (AutoCloseable scope = null) {
+ return "RETURN";
+ } catch (Throwable t) {
+ return t.toString();
+ }
+ }
+ } finally {
+ raise();
+ }
+ }
+
+ public static void raise() {
+ throw new RuntimeException();
+ }
+
+ @SuppressWarnings("try")
+ public static String snippet2() {
+ try {
+ synchronized (String.class) {
+ try (AutoCloseable scope = null) {
+ return performCompilation();
+ } catch (Throwable t) {
+ return t.toString();
+ }
+ }
+ } finally {
+ synchronized (String.class) {
+ String.class.toString();
+ }
+ }
+ }
+
+ private static String performCompilation() {
+ return "passed";
+ }
+
+ @Ignore("https://bugs.eclipse.org/bugs/show_bug.cgi?id=533187")
+ @Test
+ public void testSnippet1() {
+ OptionValues options = parseAllCodeWithoutInlining();
+ ResolvedJavaMethod method = getResolvedJavaMethod("snippet1");
+ parseEager(method, AllowAssumptions.YES, options);
+ }
+
+ @Ignore("https://bugs.eclipse.org/bugs/show_bug.cgi?id=533187")
+ @Test
+ public void testSnippet2() {
+ OptionValues options = parseAllCodeWithoutInlining();
+ ResolvedJavaMethod method = getResolvedJavaMethod("snippet2");
+ parseEager(method, AllowAssumptions.YES, options);
+ }
+
+ private static OptionValues parseAllCodeWithoutInlining() {
+ OptionValues options = new OptionValues(getInitialOptions(),
+ UseTypeCheckHints, false,
+ UseExceptionProbability, false,
+ RemoveNeverExecutedCode, false);
+ return options;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -33,9 +33,9 @@
import org.graalvm.compiler.nodes.extended.JavaWriteNode;
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
import org.graalvm.compiler.word.ObjectAccess;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
import org.junit.Assert;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -45,7 +45,7 @@
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.graalvm.compiler.replacements.CachingPEGraphDecoder;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import org.junit.Test;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,9 +37,9 @@
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.word.Word;
import org.graalvm.compiler.word.WordCastNode;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
import org.junit.Assert;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -62,7 +62,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.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,10 +26,10 @@
import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
import org.junit.Assert;
import org.junit.Assume;
-import org.junit.Ignore;
import org.junit.Test;
import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -49,6 +49,7 @@
"\uFF21\uFF21",
"\u043c\u0430\u043c\u0430\u0020\u043c\u044b\u043b\u0430\u0020\u0440\u0430\u043c\u0443\u002c\u0020\u0440\u0430\u043c\u0430\u0020\u0441\u044a\u0435\u043b\u0430\u0020\u043c\u0430\u043c\u0443",
"crazy dog jumps over laszy fox",
+ "some-string\0xff",
"XMM-XMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
"XMM-XMM+YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
"XMM-XMM-YMM-YMM+ZMM-ZMM-ZMM-ZMM-",
@@ -61,7 +62,7 @@
};
public StringCompareToTest() {
- Assume.assumeTrue(getTarget().arch instanceof AMD64);
+ Assume.assumeTrue((getTarget().arch instanceof AMD64) || (getTarget().arch instanceof AArch64));
realMethod = getResolvedJavaMethod(String.class, "compareTo", String.class);
testMethod = getResolvedJavaMethod("stringCompareTo");
@@ -91,24 +92,35 @@
}
@Test
- @Ignore("GR-8748")
public void testEqualString() {
String s = "equal-string";
executeStringCompareTo(s, new String(s.toCharArray()));
}
@Test
- @Ignore("GR-8748")
public void testDifferentString() {
- executeStringCompareTo("some-string", "different-string");
+ // Smoke test for primary cases
+ executeStringCompareTo("AAAAAAAA", "");
+ // LL
+ executeStringCompareTo("some-stringA", "some-string\0xff");
+ // UU
+ executeStringCompareTo("\u2241AAAAAAAB", "\u2241\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
+ // LU
+ executeStringCompareTo("AAAAAAAAB", "\u0041\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
}
@Test
- @Ignore("GR-8748")
public void testAllStrings() {
for (String s0 : testData) {
for (String s1 : testData) {
- executeStringCompareTo(s0, s1);
+ try {
+ executeStringCompareTo(s0, s1);
+ } catch (AssertionError ex) {
+ System.out.println("FAIL: '" + ex + "'");
+ System.out.println(" ***: s0 '" + s0 + "'");
+ System.out.println(" ***: s1 '" + s1 + "'");
+ throw ex;
+ }
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,10 +29,10 @@
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
import org.junit.Test;
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -149,7 +149,7 @@
for (final Enumeration<? extends ZipEntry> entry = zipFile.entries(); entry.hasMoreElements();) {
final ZipEntry zipEntry = entry.nextElement();
String name = zipEntry.getName();
- if (name.endsWith(".class") && !name.equals("module-info.class")) {
+ if (name.endsWith(".class") && !name.equals("module-info.class") && !name.startsWith("META-INF/versions/")) {
String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
if (isInNativeImage(className)) {
/*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.SourceLanguagePositionProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -48,6 +48,7 @@
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
+import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
@@ -131,7 +132,7 @@
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.MemoryBarriers;
@@ -526,7 +527,8 @@
ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue());
AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset()));
- LogicCompareAndSwapNode atomicNode = graph.add(new LogicCompareAndSwapNode(address, cas.getLocationIdentity(), expectedValue, newValue, compareAndSwapBarrierType(cas)));
+ BarrierType barrierType = storeBarrierType(cas.object(), expectedValue);
+ LogicCompareAndSwapNode atomicNode = graph.add(new LogicCompareAndSwapNode(address, cas.getLocationIdentity(), expectedValue, newValue, barrierType));
atomicNode.setStateAfter(cas.stateAfter());
graph.replaceFixedWithFixed(cas, atomicNode);
}
@@ -538,7 +540,8 @@
ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
AddressNode address = graph.unique(new OffsetAddressNode(n.object(), n.offset()));
- LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, atomicReadAndWriteBarrierType(n)));
+ BarrierType barrierType = storeBarrierType(n.object(), n.newValue());
+ LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, barrierType));
memoryRead.setStateAfter(n.stateAfter());
ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
@@ -673,6 +676,7 @@
memoryWrite.setGuard(write.getGuard());
}
+ @SuppressWarnings("try")
protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) {
StructuredGraph graph = commit.graph();
if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
@@ -685,10 +689,12 @@
VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
int entryCount = virtual.entryCount();
AbstractNewObjectNode newObject;
- if (virtual instanceof VirtualInstanceNode) {
- newObject = graph.add(createNewInstanceFromVirtual(virtual));
- } else {
- newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph)));
+ try (DebugCloseable nsp = virtual.withNodeSourcePosition()) {
+ if (virtual instanceof VirtualInstanceNode) {
+ newObject = graph.add(createNewInstanceFromVirtual(virtual));
+ } else {
+ newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph)));
+ }
}
recursiveLowerings.add(newObject);
graph.addBeforeFixed(commit, newObject);
@@ -884,23 +890,15 @@
return entryKind == JavaKind.Object ? BarrierType.PRECISE : BarrierType.NONE;
}
- protected BarrierType unsafeStoreBarrierType(RawStoreNode store) {
+ private static BarrierType unsafeStoreBarrierType(RawStoreNode store) {
if (!store.needsBarrier()) {
return BarrierType.NONE;
}
return storeBarrierType(store.object(), store.value());
}
- protected BarrierType compareAndSwapBarrierType(UnsafeCompareAndSwapNode cas) {
- return storeBarrierType(cas.object(), cas.expected());
- }
-
- protected BarrierType atomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) {
- return storeBarrierType(n.object(), n.newValue());
- }
-
- protected BarrierType storeBarrierType(ValueNode object, ValueNode value) {
- if (value.getStackKind() == JavaKind.Object) {
+ private static BarrierType storeBarrierType(ValueNode object, ValueNode value) {
+ if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) {
ResolvedJavaType type = StampTool.typeOrNull(object);
if (type != null && !type.isArray()) {
return BarrierType.IMPRECISE;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,10 +29,12 @@
import java.util.ArrayList;
import java.util.List;
+import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.debug.DebugCloseable;
+import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node.ValueNumberable;
@@ -71,7 +73,7 @@
import org.graalvm.compiler.phases.common.inlining.InliningUtil;
import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -99,9 +101,20 @@
protected abstract static class Structure {
}
- public GraphKit(StructuredGraph graph, Providers providers, WordTypes wordTypes, GraphBuilderConfiguration.Plugins graphBuilderPlugins) {
+ public GraphKit(DebugContext debug, ResolvedJavaMethod stubMethod, Providers providers, WordTypes wordTypes, Plugins graphBuilderPlugins, CompilationIdentifier compilationId, String name) {
this.providers = providers;
- this.graph = graph;
+ StructuredGraph.Builder builder = new StructuredGraph.Builder(debug.getOptions(), debug).compilationId(compilationId);
+ if (name != null) {
+ builder.name(name);
+ } else {
+ builder.method(stubMethod);
+ }
+ this.graph = builder.build();
+ graph.disableUnsafeAccessTracking();
+ if (graph.trackNodeSourcePosition()) {
+ // Set up a default value that everything constructed by GraphKit will use.
+ graph.withNodeSourcePosition(NodeSourcePosition.substitution(stubMethod));
+ }
this.wordTypes = wordTypes;
this.graphBuilderPlugins = graphBuilderPlugins;
this.lastFixedNode = graph.start();
@@ -229,7 +242,7 @@
*/
@SuppressWarnings("try")
public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
- try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.placeholder(method))) {
+ try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(graph.currentNodeSourcePosition(), method))) {
assert method.isStatic() == (invokeKind == InvokeKind.Static);
Signature signature = method.getSignature();
JavaType returnType = signature.getReturnType(null);
@@ -254,15 +267,29 @@
}
}
+ @SuppressWarnings("try")
public InvokeWithExceptionNode createInvokeWithExceptionAndUnwind(ResolvedJavaMethod method, InvokeKind invokeKind,
FrameStateBuilder frameStateBuilder, int invokeBci, int exceptionEdgeBci, ValueNode... args) {
+ try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(graph.currentNodeSourcePosition(), method))) {
+ InvokeWithExceptionNode result = startInvokeWithException(method, invokeKind, frameStateBuilder, invokeBci, exceptionEdgeBci, args);
+ exceptionPart();
+ ExceptionObjectNode exception = exceptionObject();
+ append(new UnwindNode(exception));
+ endInvokeWithException();
+ return result;
+ }
+ }
- InvokeWithExceptionNode result = startInvokeWithException(method, invokeKind, frameStateBuilder, invokeBci, exceptionEdgeBci, args);
- exceptionPart();
- ExceptionObjectNode exception = exceptionObject();
- append(new UnwindNode(exception));
- endInvokeWithException();
- return result;
+ @SuppressWarnings("try")
+ public InvokeWithExceptionNode createInvokeWithExceptionAndUnwind(MethodCallTargetNode callTarget, FrameStateBuilder frameStateBuilder, int invokeBci, int exceptionEdgeBci) {
+ try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(graph.currentNodeSourcePosition(), callTarget.targetMethod()))) {
+ InvokeWithExceptionNode result = startInvokeWithException(callTarget, frameStateBuilder, invokeBci, exceptionEdgeBci);
+ exceptionPart();
+ ExceptionObjectNode exception = exceptionObject();
+ append(new UnwindNode(exception));
+ endInvokeWithException();
+ return result;
+ }
}
protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, @SuppressWarnings("unused") int bci) {
@@ -305,10 +332,10 @@
/**
* Recursively {@linkplain #inline inlines} all invocations currently in the graph.
*/
- public void inlineInvokes() {
+ public void inlineInvokes(String reason, String phase) {
while (!graph.getNodes().filter(InvokeNode.class).isEmpty()) {
for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) {
- inline(invoke);
+ inline(invoke, reason, phase);
}
}
@@ -320,7 +347,7 @@
* Inlines a given invocation to a method. The graph of the inlined method is processed in the
* same manner as for snippets and method substitutions.
*/
- public void inline(InvokeNode invoke) {
+ public void inline(InvokeNode invoke, String reason, String phase) {
ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
MetaAccessProvider metaAccess = providers.getMetaAccess();
@@ -341,7 +368,7 @@
calleeGraph.clearAllStateAfter();
new DeadCodeEliminationPhase(Optionality.Required).apply(calleeGraph);
- InliningUtil.inline(invoke, calleeGraph, false, method);
+ InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase);
}
protected void pushStructure(Structure structure) {
@@ -493,6 +520,11 @@
if (returnStamp == null) {
returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false);
}
+ MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnStamp, invokeBci));
+ return startInvokeWithException(callTarget, frameStateBuilder, invokeBci, exceptionEdgeBci);
+ }
+
+ public InvokeWithExceptionNode startInvokeWithException(MethodCallTargetNode callTarget, FrameStateBuilder frameStateBuilder, int invokeBci, int exceptionEdgeBci) {
ExceptionObjectNode exceptionObject = add(new ExceptionObjectNode(getMetaAccess()));
if (frameStateBuilder != null) {
FrameStateBuilder exceptionState = frameStateBuilder.copy();
@@ -501,7 +533,6 @@
exceptionState.setRethrowException(false);
exceptionObject.setStateAfter(exceptionState.create(exceptionEdgeBci, exceptionObject));
}
- MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnStamp, invokeBci));
InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionObject, invokeBci));
AbstractBeginNode noExceptionEdge = graph.add(KillingBeginNode.create(LocationIdentity.any()));
invoke.setNext(noExceptionEdge);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.replacements;
+import static org.graalvm.compiler.core.common.GraalOptions.MaximumRecursiveInlining;
+
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.nodes.CallTargetNode;
@@ -46,6 +48,16 @@
this.safeForDeoptimization = safeForDeoptimization;
}
+ private static int countRecursiveInlining(GraphBuilderContext b, ResolvedJavaMethod method) {
+ int count = 0;
+ for (GraphBuilderContext c = b.getParent(); c != null; c = c.getParent()) {
+ if (method.equals(c.getMethod())) {
+ count++;
+ }
+ }
+ return count;
+ }
+
@Override
public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
IntrinsicMethod intrinsicMethod = methodHandleAccess.lookupMethodHandleIntrinsic(method);
@@ -83,11 +95,19 @@
// As such, it needs to recursively inline everything.
inlineEverything = args.length != argumentsList.size();
}
- if (inlineEverything && !callTarget.targetMethod().hasBytecodes()) {
+ ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+ if (inlineEverything && !targetMethod.hasBytecodes()) {
// we need to force-inline but we can not, leave the invoke as-is
return false;
}
- b.handleReplacedInvoke(invoke.getInvokeKind(), callTarget.targetMethod(), argumentsList.toArray(new ValueNode[argumentsList.size()]), inlineEverything);
+
+ int recursionDepth = countRecursiveInlining(b, targetMethod);
+ int maxRecursionDepth = MaximumRecursiveInlining.getValue(b.getOptions());
+ if (recursionDepth > maxRecursionDepth) {
+ return false;
+ }
+
+ b.handleReplacedInvoke(invoke.getInvokeKind(), targetMethod, argumentsList.toArray(new ValueNode[argumentsList.size()]), inlineEverything);
}
return true;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
import java.util.List;
import java.util.Map;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.PermanentBailoutException;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,8 +36,8 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.api.replacements.MethodSubstitution;
import org.graalvm.compiler.api.replacements.Snippet;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -50,7 +50,7 @@
import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
import org.graalvm.compiler.word.ObjectAccess;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.TargetDescription;
import sun.misc.Unsafe;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetLowerableMemoryNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetLowerableMemoryNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
import org.graalvm.compiler.nodes.memory.MemoryNode;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
@NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
public class SnippetLowerableMemoryNode extends FixedWithNextNode implements Lowerable, MemoryAccess {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
@@ -47,10 +47,10 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
@@ -131,8 +131,8 @@
import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
import org.graalvm.compiler.replacements.nodes.LoadSnippetVarargParameterNode;
import org.graalvm.util.CollectionsUtil;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordBase;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.meta.Constant;
@@ -651,8 +651,9 @@
try (DebugContext debug = openDebugContext(outer, args)) {
try (DebugCloseable a = SnippetTemplateCreationTime.start(debug); DebugContext.Scope s = debug.scope("SnippetSpecialization", args.info.method)) {
SnippetTemplates.increment(debug);
- template = new SnippetTemplate(options, debug, providers, snippetReflection, args, graph.trackNodeSourcePosition(), replacee);
- if (Options.UseSnippetTemplateCache.getValue(options) && args.cacheable) {
+ OptionValues snippetOptions = new OptionValues(options, GraalOptions.TraceInlining, GraalOptions.TraceInliningForStubsAndSnippets.getValue(options));
+ template = new SnippetTemplate(snippetOptions, debug, providers, snippetReflection, args, graph.trackNodeSourcePosition(), replacee);
+ if (Options.UseSnippetTemplateCache.getValue(snippetOptions) && args.cacheable) {
templates.put(args.cacheKey, template);
}
} catch (Throwable e) {
@@ -1516,9 +1517,7 @@
replaceeGraph.getInliningLog().addLog(duplicates, snippet.getInliningLog());
}
NodeSourcePosition position = replacee.getNodeSourcePosition();
- if (position != null) {
- InliningUtil.updateSourcePosition(replaceeGraph, duplicates, mark, position, true);
- }
+ InliningUtil.updateSourcePosition(replaceeGraph, duplicates, mark, position, true);
debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
return duplicates;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
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.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -105,7 +105,7 @@
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactNode;
import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
@@ -233,10 +233,10 @@
// Ordered object-based accesses
if (Java8OrEarlier) {
if (kind == JavaKind.Int || kind == JavaKind.Long || kind == JavaKind.Object) {
- r.register4("putOrdered" + kindName, Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, true));
+ r.register4("putOrdered" + kindName, Receiver.class, Object.class, long.class, javaClass, UnsafePutPlugin.putOrdered(kind));
}
} else {
- r.register4("put" + kindName + "Release", Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, true));
+ r.register4("put" + kindName + "Release", Receiver.class, Object.class, long.class, javaClass, UnsafePutPlugin.putOrdered(kind));
}
if (kind != JavaKind.Boolean && kind != JavaKind.Object) {
// Raw accesses to memory addresses
@@ -693,15 +693,29 @@
public static class UnsafePutPlugin implements InvocationPlugin {
private final JavaKind kind;
- private final boolean isVolatile;
+ private final boolean hasBarrier;
+ private final int preWrite;
+ private final int postWrite;
public UnsafePutPlugin(JavaKind kind, boolean isVolatile) {
+ this(kind, isVolatile, JMM_PRE_VOLATILE_WRITE, JMM_POST_VOLATILE_WRITE);
+ }
+
+ private UnsafePutPlugin(JavaKind kind, boolean hasBarrier, int preWrite, int postWrite) {
+ super();
this.kind = kind;
- this.isVolatile = isVolatile;
+ this.hasBarrier = hasBarrier;
+ this.preWrite = preWrite;
+ this.postWrite = postWrite;
+ }
+
+ public static UnsafePutPlugin putOrdered(JavaKind kind) {
+ return new UnsafePutPlugin(kind, true, LOAD_STORE | STORE_STORE, 0);
}
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode address, ValueNode value) {
+ assert !hasBarrier : "Barriers for address based Unsafe put is not supported.";
// Emits a null-check for the otherwise unused receiver
unsafe.get();
b.add(new UnsafeMemoryStoreNode(address, value, kind, OFF_HEAP_LOCATION));
@@ -713,13 +727,13 @@
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode value) {
// Emits a null-check for the otherwise unused receiver
unsafe.get();
- if (isVolatile) {
- b.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
+ if (hasBarrier) {
+ b.add(new MembarNode(preWrite));
}
LocationIdentity locationIdentity = object.isNullConstant() ? OFF_HEAP_LOCATION : LocationIdentity.any();
b.add(new RawStoreNode(object, offset, value, kind, locationIdentity));
- if (isVolatile) {
- b.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
+ if (hasBarrier) {
+ b.add(new MembarNode(postWrite));
}
b.getGraph().markUnsafeAccess();
return true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,19 +22,16 @@
*/
package org.graalvm.compiler.replacements.classfile;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getModule;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getResourceAsStream;
-
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.bytecode.BytecodeProvider;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -98,20 +95,6 @@
return false;
}
- private static InputStream getClassfileAsStream(Class<?> c) {
- String classfilePath = c.getName().replace('.', '/') + ".class";
- if (JDK9Method.JAVA_SPECIFICATION_VERSION >= 9) {
- Object module = getModule(c);
- return getResourceAsStream(module, classfilePath);
- } else {
- ClassLoader cl = c.getClassLoader();
- if (cl == null) {
- return ClassLoader.getSystemResourceAsStream(classfilePath);
- }
- return cl.getResourceAsStream(classfilePath);
- }
- }
-
/**
* Gets a {@link Classfile} created by parsing the class file bytes for {@code c}.
*
@@ -123,7 +106,7 @@
if (classfile == null) {
try {
ResolvedJavaType type = metaAccess.lookupJavaType(c);
- InputStream in = getClassfileAsStream(c);
+ InputStream in = GraalServices.getClassfileAsStream(c);
if (in != null) {
DataInputStream stream = new DataInputStream(in);
classfile = new Classfile(type, stream, this);
--- /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/classfile/D Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,102 @@
+diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java
+index 88403c3..728297d 100644
+--- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java
++++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java
+@@ -138,7 +138,11 @@ public final class ClassfileBytecodeProvider implements BytecodeProvider {
+ return classfile;
+ }
+
+- synchronized Class<?> resolveToClass(String descriptor) {
++ Class<?> resolveToClass(String descriptor) {
++ return resolveToClass(descriptor, false);
++ }
++
++ synchronized Class<?> resolveToClass(String descriptor, boolean initialize) {
+ Class<?> c = classes.get(descriptor);
+ if (c == null) {
+ if (descriptor.length() == 1) {
+@@ -155,7 +159,7 @@ public final class ClassfileBytecodeProvider implements BytecodeProvider {
+ name = descriptor.replace('/', '.');
+ }
+ try {
+- c = Class.forName(name, true, loader);
++ c = Class.forName(name, initialize, loader);
+ classes.put(descriptor, c);
+ } catch (ClassNotFoundException e) {
+ throw new NoClassDefFoundError(descriptor);
+diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java
+index 087f78b..bde2dd4 100644
+--- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java
++++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java
+@@ -70,8 +70,9 @@ abstract class ClassfileConstant {
+ * @param cp
+ * @param index
+ * @param opcode
++ * @param initialize
+ */
+- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
++ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
+ }
+
+ @Override
+@@ -90,15 +91,19 @@ abstract class ClassfileConstant {
+ }
+
+ @Override
+- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
+- resolve(cp);
++ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
++ resolve(cp, initialize);
+ }
+
+ public ResolvedJavaType resolve(ClassfileConstantPool cp) throws GraalError {
++ return resolve(cp, false /* initialize */);
++ }
++
++ public ResolvedJavaType resolve(ClassfileConstantPool cp, boolean initialize) throws GraalError {
+ if (type == null) {
+ String typeDescriptor = cp.get(Utf8.class, nameIndex).value;
+ ClassfileBytecodeProvider context = cp.context;
+- type = context.metaAccess.lookupJavaType(context.resolveToClass(typeDescriptor));
++ type = context.metaAccess.lookupJavaType(context.resolveToClass(typeDescriptor, initialize));
+ }
+ return type;
+ }
+@@ -116,8 +121,8 @@ abstract class ClassfileConstant {
+ }
+
+ @Override
+- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
+- cp.get(ClassRef.class, classIndex).loadReferencedType(cp, classIndex, opcode);
++ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
++ cp.get(ClassRef.class, classIndex).loadReferencedType(cp, classIndex, opcode, initialize);
+ }
+ }
+
+@@ -269,7 +274,7 @@ abstract class ClassfileConstant {
+ }
+
+ @Override
+- public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
++ public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
+ throw new GraalError("Resolution of " + name + " constant pool entries not supported by " + ClassfileBytecodeProvider.class.getSimpleName());
+ }
+ }
+diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java
+index 218df10..a54779b 100644
+--- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java
++++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java
+@@ -133,11 +133,11 @@ class ClassfileConstantPool implements ConstantPool {
+ }
+
+ @Override
+- public void loadReferencedType(int index, int opcode) {
++ public void loadReferencedType(int index, int opcode, boolean initialize) {
+ if (opcode == Bytecodes.INVOKEDYNAMIC) {
+ throw new GraalError("INVOKEDYNAMIC not supported by " + ClassfileBytecodeProvider.class.getSimpleName());
+ }
+- entries[index].loadReferencedType(this, index, opcode);
++ entries[index].loadReferencedType(this, index, opcode, initialize);
+ }
+
+ @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayCompareToNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayCompareToNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -44,7 +44,7 @@
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -46,7 +46,7 @@
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.nodeinfo.InputType.Memory;
import static org.graalvm.compiler.nodeinfo.InputType.State;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.DebugContext;
@@ -51,7 +51,7 @@
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -189,7 +189,7 @@
((Lowerable) nonNullReceiver).lower(tool);
}
}
- InliningUtil.inline(invoke, replacementGraph, false, targetMethod);
+ InliningUtil.inline(invoke, replacementGraph, false, targetMethod, "Replace with graph.", "LoweringPhase");
replacementGraph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph(), "After inlining replacement %s", replacementGraph);
} else {
if (isPlaceholderBci(invoke.bci())) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,53 +22,44 @@
*/
package org.graalvm.compiler.serviceprovider;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.addOpens;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getModule;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getPackages;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.isOpenTo;
+import static java.lang.Thread.currentThread;
-import java.lang.reflect.Method;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.Iterator;
+import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
-import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
import jdk.vm.ci.services.JVMCIPermission;
import jdk.vm.ci.services.Services;
/**
- * A mechanism for accessing service providers that abstracts over whether Graal is running on
- * JVMCI-8 or JVMCI-9. In JVMCI-8, a JVMCI specific mechanism is used to lookup services via the
- * hidden JVMCI class loader. In JVMCI-9, the standard {@link ServiceLoader} mechanism is used.
+ * Interface to functionality that abstracts over which JDK version Graal is running on.
*/
public final class GraalServices {
- private GraalServices() {
+ private static int getJavaSpecificationVersion() {
+ String value = System.getProperty("java.specification.version");
+ if (value.startsWith("1.")) {
+ value = value.substring(2);
+ }
+ return Integer.parseInt(value);
}
/**
- * Opens all JVMCI packages to the module of a given class. This relies on JVMCI already having
- * opened all its packages to the module defining {@link GraalServices}.
- *
- * @param other all JVMCI packages will be opened to the module defining this class
+ * 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 void openJVMCITo(Class<?> other) {
- Object jvmci = getModule(Services.class);
- Object otherModule = getModule(other);
- if (jvmci != otherModule) {
- Set<String> packages = getPackages(jvmci);
- for (String pkg : packages) {
- boolean opened = isOpenTo(jvmci, pkg, otherModule);
- if (!opened) {
- try {
- addOpens.invoke(jvmci, pkg, otherModule);
- } catch (Throwable throwable) {
- throw new InternalError(throwable);
- }
- }
- }
- }
+ 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;
+
+ private GraalServices() {
}
/**
@@ -79,15 +70,12 @@
*/
public static <S> Iterable<S> load(Class<S> service) {
assert !service.getName().startsWith("jdk.vm.ci") : "JVMCI services must be loaded via " + Services.class.getName();
- if (Java8OrEarlier) {
- return load8(service);
- }
Iterable<S> iterable = ServiceLoader.load(service);
- return new Iterable<S>() {
+ return new Iterable<>() {
@Override
public Iterator<S> iterator() {
Iterator<S> iterator = iterable.iterator();
- return new Iterator<S>() {
+ return new Iterator<>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
@@ -111,19 +99,20 @@
}
/**
- * {@code Services.load(Class)} is only defined in JVMCI-8.
+ * Opens all JVMCI packages to the module of a given class. This relies on JVMCI already having
+ * opened all its packages to the module defining {@link GraalServices}.
+ *
+ * @param other all JVMCI packages will be opened to the module defining this class
*/
- private static volatile Method loadMethod;
-
- @SuppressWarnings("unchecked")
- private static <S> Iterable<S> load8(Class<S> service) throws InternalError {
- try {
- if (loadMethod == null) {
- loadMethod = Services.class.getMethod("load", Class.class);
+ static void openJVMCITo(Class<?> other) {
+ Module jvmciModule = JVMCI_MODULE;
+ Module otherModule = other.getModule();
+ if (jvmciModule != otherModule) {
+ for (String pkg : jvmciModule.getPackages()) {
+ if (!jvmciModule.isOpen(pkg, otherModule)) {
+ jvmciModule.addOpens(pkg, otherModule);
+ }
}
- return (Iterable<S>) loadMethod.invoke(null, service);
- } catch (Exception e) {
- throw new InternalError(e);
}
}
@@ -159,4 +148,185 @@
}
return singleProvider;
}
+
+ /**
+ * Gets the class file bytes for {@code c}.
+ */
+ public static InputStream getClassfileAsStream(Class<?> c) throws IOException {
+ String classfilePath = c.getName().replace('.', '/') + ".class";
+ return c.getModule().getResourceAsStream(classfilePath);
+ }
+
+ private static final Module JVMCI_MODULE = Services.class.getModule();
+
+ /**
+ * A JVMCI package dynamically exported to trusted modules.
+ */
+ private static final String JVMCI_RUNTIME_PACKAGE = "jdk.vm.ci.runtime";
+ static {
+ assert JVMCI_MODULE.getPackages().contains(JVMCI_RUNTIME_PACKAGE);
+ }
+
+ /**
+ * Determines if invoking {@link Object#toString()} on an instance of {@code c} will only run
+ * trusted code.
+ */
+ public static boolean isToStringTrusted(Class<?> c) {
+ Module module = c.getModule();
+ Module jvmciModule = JVMCI_MODULE;
+ assert jvmciModule.getPackages().contains("jdk.vm.ci.runtime");
+ if (module == jvmciModule || jvmciModule.isOpen(JVMCI_RUNTIME_PACKAGE, module)) {
+ // Can access non-statically-exported package in JVMCI
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets a unique identifier for this execution such as a process ID or a
+ * {@linkplain #getGlobalTimeStamp() fixed timestamp}.
+ */
+ public static String getExecutionID() {
+ return Long.toString(ProcessHandle.current().pid());
+ }
+
+ private static final AtomicLong globalTimeStamp = new AtomicLong();
+
+ /**
+ * Gets a time stamp for the current process. This method will always return the same value for
+ * the current VM execution.
+ */
+ public static long getGlobalTimeStamp() {
+ if (globalTimeStamp.get() == 0) {
+ globalTimeStamp.compareAndSet(0, System.currentTimeMillis());
+ }
+ return globalTimeStamp.get();
+ }
+
+ /**
+ * Access to thread specific information made available via Java Management Extensions (JMX).
+ * Using this abstraction enables avoiding a dependency to the {@code java.management} and
+ * {@code jdk.management} modules on JDK 9 and later.
+ */
+ public abstract static class JMXService {
+ protected abstract long getThreadAllocatedBytes(long id);
+
+ protected abstract long getCurrentThreadCpuTime();
+
+ protected abstract boolean isThreadAllocatedMemorySupported();
+
+ protected abstract boolean isCurrentThreadCpuTimeSupported();
+
+ protected abstract List<String> getInputArguments();
+
+ // Placing this static field in JMXService (instead of GraalServices)
+ // allows for lazy initialization.
+ static final JMXService instance = loadSingle(JMXService.class, false);
+ }
+
+ /**
+ * Returns an approximation of the total amount of memory, in bytes, allocated in heap memory
+ * for the thread of the specified ID. The returned value is an approximation because some Java
+ * virtual machine implementations may use object allocation mechanisms that result in a delay
+ * between the time an object is allocated and the time its size is recorded.
+ * <p>
+ * If the thread of the specified ID is not alive or does not exist, this method returns
+ * {@code -1}. If thread memory allocation measurement is disabled, this method returns
+ * {@code -1}. A thread is alive if it has been started and has not yet died.
+ * <p>
+ * If thread memory allocation measurement is enabled after the thread has started, the Java
+ * virtual machine implementation may choose any time up to and including the time that the
+ * capability is enabled as the point where thread memory allocation measurement starts.
+ *
+ * @param id the thread ID of a thread
+ * @return an approximation of the total memory allocated, in bytes, in heap memory for a thread
+ * of the specified ID if the thread of the specified ID exists, the thread is alive,
+ * and thread memory allocation measurement is enabled; {@code -1} otherwise.
+ *
+ * @throws IllegalArgumentException if {@code id} {@code <=} {@code 0}.
+ * @throws UnsupportedOperationException if the Java virtual machine implementation does not
+ * {@linkplain #isThreadAllocatedMemorySupported() support} thread memory allocation
+ * measurement.
+ */
+ public static long getThreadAllocatedBytes(long id) {
+ JMXService jmx = JMXService.instance;
+ if (jmx == null) {
+ throw new UnsupportedOperationException();
+ }
+ return jmx.getThreadAllocatedBytes(id);
+ }
+
+ /**
+ * Convenience method for calling {@link #getThreadAllocatedBytes(long)} with the id of the
+ * current thread.
+ */
+ public static long getCurrentThreadAllocatedBytes() {
+ return getThreadAllocatedBytes(currentThread().getId());
+ }
+
+ /**
+ * Returns the total CPU time for the current thread in nanoseconds. The returned value is of
+ * nanoseconds precision but not necessarily nanoseconds accuracy. If the implementation
+ * distinguishes between user mode time and system mode time, the returned CPU time is the
+ * amount of time that the current thread has executed in user mode or system mode.
+ *
+ * @return the total CPU time for the current thread if CPU time measurement is enabled;
+ * {@code -1} otherwise.
+ *
+ * @throws UnsupportedOperationException if the Java virtual machine does not
+ * {@linkplain #isCurrentThreadCpuTimeSupported() support} CPU time measurement for
+ * the current thread
+ */
+ public static long getCurrentThreadCpuTime() {
+ JMXService jmx = JMXService.instance;
+ if (jmx == null) {
+ throw new UnsupportedOperationException();
+ }
+ return jmx.getCurrentThreadCpuTime();
+ }
+
+ /**
+ * Determines if the Java virtual machine implementation supports thread memory allocation
+ * measurement.
+ */
+ public static boolean isThreadAllocatedMemorySupported() {
+ JMXService jmx = JMXService.instance;
+ if (jmx == null) {
+ return false;
+ }
+ return jmx.isThreadAllocatedMemorySupported();
+ }
+
+ /**
+ * Determines if the Java virtual machine supports CPU time measurement for the current thread.
+ */
+ public static boolean isCurrentThreadCpuTimeSupported() {
+ JMXService jmx = JMXService.instance;
+ if (jmx == null) {
+ return false;
+ }
+ return jmx.isCurrentThreadCpuTimeSupported();
+ }
+
+ /**
+ * Gets the input arguments passed to the Java virtual machine which does not include the
+ * arguments to the {@code main} method. This method returns an empty list if there is no input
+ * argument to the Java virtual machine.
+ * <p>
+ * Some Java virtual machine implementations may take input arguments from multiple different
+ * sources: for examples, arguments passed from the application that launches the Java virtual
+ * machine such as the 'java' command, environment variables, configuration files, etc.
+ * <p>
+ * Typically, not all command-line options to the 'java' command are passed to the Java virtual
+ * machine. Thus, the returned input arguments may not include all command-line options.
+ *
+ * @return the input arguments to the JVM or {@code null} if they are unavailable
+ */
+ public static List<String> getInputArguments() {
+ JMXService jmx = JMXService.instance;
+ if (jmx == null) {
+ return null;
+ }
+ return jmx.getInputArguments();
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JDK9Method.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.serviceprovider;
-
-import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Method;
-import java.util.Set;
-
-/**
- * Reflection based access to API introduced by JDK 9. This allows the API to be used in code that
- * must be compiled on a JDK prior to 9.
- */
-public final class JDK9Method {
-
- private static int getJavaSpecificationVersion() {
- String value = System.getProperty("java.specification.version");
- if (value.startsWith("1.")) {
- value = value.substring(2);
- }
- return Integer.parseInt(value);
- }
-
- /**
- * 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();
-
- public static MethodHandle lookupMethodHandle(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
- try {
- return MethodHandles.lookup().unreflect(declaringClass.getMethod(name, parameterTypes));
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
-
- private static Method lookupMethod(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
- try {
- return declaringClass.getMethod(name, parameterTypes);
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
-
- /**
- * Determines if the Java runtime is version 8 or earlier.
- */
- public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8;
-
- /**
- * {@code Class.getModule()}.
- */
- private static final MethodHandle getModuleHandle;
-
- public static Object getModule(Class<?> clazz) {
- try {
- return getModuleHandle.invoke(clazz);
- } catch (Throwable throwable) {
- throw new InternalError(throwable);
- }
- }
-
- /**
- * {@code java.lang.Module.getPackages()}.
- */
- private static final MethodHandle getPackages;
-
- public static Set<String> getPackages(Object module) {
- try {
- return (Set<String>) getPackages.invoke(module);
- } catch (Throwable throwable) {
- throw new InternalError(throwable);
- }
- }
-
- /**
- * {@code java.lang.Module.getResourceAsStream(String)}.
- */
- private static final MethodHandle getResourceAsStream;
-
- public static InputStream getResourceAsStream(Object module, String resource) {
- try {
- return (InputStream) getResourceAsStream.invoke(module, resource);
- } catch (Throwable throwable) {
- throw new InternalError(throwable);
- }
- }
-
- /**
- * {@code java.lang.Module.addOpens(String, Module)}. This only seems to work correctly when
- * invoked through reflection.
- */
- public static final Method addOpens;
-
- /**
- * {@code java.lang.Module.isOpen(String, Module)}.
- */
- private static final MethodHandle isOpenTo;
-
- public static boolean isOpenTo(Object module1, String pkg, Object module2) {
- try {
- return (boolean) isOpenTo.invoke(module1, pkg, module2);
- } catch (Throwable throwable) {
- throw new InternalError(throwable);
- }
- }
-
- public static final Class<?> MODULE_CLASS;
-
- static {
- if (JAVA_SPECIFICATION_VERSION >= 9) {
- try {
- MODULE_CLASS = Class.class.getMethod("getModule").getReturnType();
- getModuleHandle = lookupMethodHandle(Class.class, "getModule");
- getPackages = lookupMethodHandle(MODULE_CLASS, "getPackages");
- addOpens = lookupMethod(MODULE_CLASS, "addOpens", String.class, MODULE_CLASS);
- getResourceAsStream = lookupMethodHandle(MODULE_CLASS, "getResourceAsStream", String.class);
- isOpenTo = lookupMethodHandle(MODULE_CLASS, "isOpen", String.class, MODULE_CLASS);
- } catch (NoSuchMethodException e) {
- throw new InternalError(e);
- }
- } else {
- MODULE_CLASS = null;
- getModuleHandle = null;
- getPackages = null;
- addOpens = null;
- getResourceAsStream = null;
- isOpenTo = null;
- }
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -40,6 +40,7 @@
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.GlobalMetrics;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import org.junit.After;
import org.junit.Assert;
import org.junit.internal.ComparisonCriteria;
@@ -64,7 +65,7 @@
}
}
- public static final boolean Java8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
+ public static final boolean Java8OrEarlier = GraalServices.Java8OrEarlier;
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/SubprocessUtil.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.graalvm.compiler.serviceprovider.GraalServices;
import org.graalvm.util.CollectionsUtil;
/**
@@ -236,7 +237,7 @@
return new Subprocess(command, process.waitFor(), output);
}
- private static final boolean isJava8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
+ private static final boolean isJava8OrEarlier = GraalServices.Java8OrEarlier;
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.bench/.checkstyle.exclude Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-src_gen
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
import java.util.Iterator;
import java.util.Map;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
public abstract class EffectsBlockState<T extends EffectsBlockState<T>> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,9 +25,9 @@
import java.util.ArrayList;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.type.Stamp;
@@ -62,7 +62,7 @@
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.LoopInfo;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.core.common.util.CompilationAlarm;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Graph.NodeEventScope;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
import java.util.Iterator;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.DebugContext;
@@ -37,7 +37,7 @@
import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,11 +29,11 @@
import java.util.Iterator;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.graph.Node;
@@ -66,7 +66,7 @@
import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Thu Apr 26 17:59:02 2018 +0200
@@ -28,9 +28,9 @@
import java.util.List;
import java.util.function.IntUnaryOperator;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalysisIterations;
import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalyzeOnly;
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,10 +24,10 @@
import java.util.Iterator;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
/**
* This class maintains a set of known values, identified by base object, locations and offset.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java Thu Apr 26 17:59:02 2018 +0200
@@ -23,15 +23,15 @@
package org.graalvm.compiler.virtual.phases.ea;
import static org.graalvm.compiler.core.common.GraalOptions.ReadEliminationMaxLoopVisits;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import java.util.Iterator;
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
import org.graalvm.compiler.core.common.cfg.Loop;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
@@ -63,7 +63,7 @@
import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.util.List;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TTY;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/BarrieredAccess.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/BarrieredAccess.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,11 +24,11 @@
import org.graalvm.compiler.word.Word.Opcode;
import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
/**
* Medium-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/ObjectAccess.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/ObjectAccess.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,11 +24,11 @@
import org.graalvm.compiler.word.Word.Opcode;
import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
/**
* Low-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java Thu Apr 26 17:59:02 2018 +0200
@@ -48,19 +48,19 @@
import org.graalvm.compiler.nodes.calc.XorNode;
import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
import org.graalvm.compiler.nodes.memory.address.AddressNode.Address;
-import org.graalvm.word.ComparableWord;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.ComparableWord;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
+import jdk.internal.vm.compiler.word.impl.WordBoxFactory;
-public abstract class Word extends WordFactory implements SignedWord, UnsignedWord, Pointer {
+public abstract class Word implements SignedWord, UnsignedWord, Pointer {
static {
- assert WordFactory.boxFactory == null : "BoxFactory must be initialized only once.";
- WordFactory.boxFactory = new BoxFactoryImpl();
+ BoxFactoryImpl.initialize();
}
public static void ensureInitialized() {
@@ -109,10 +109,15 @@
TO_RAW_VALUE,
}
- public static class BoxFactoryImpl implements BoxFactory {
+ static class BoxFactoryImpl extends WordBoxFactory {
+ static void initialize() {
+ assert boxFactory == null : "BoxFactory must be initialized only once.";
+ boxFactory = new BoxFactoryImpl();
+ }
+
@SuppressWarnings("unchecked")
@Override
- public <T extends WordBase> T box(long val) {
+ public <T extends WordBase> T boxImpl(long val) {
return (T) HostedWord.boxLong(val);
}
}
@@ -697,55 +702,55 @@
@Override
@Operation(opcode = Opcode.READ_POINTER)
public byte readByte(int offset, LocationIdentity locationIdentity) {
- return readByte(signed(offset), locationIdentity);
+ return readByte(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public char readChar(int offset, LocationIdentity locationIdentity) {
- return readChar(signed(offset), locationIdentity);
+ return readChar(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public short readShort(int offset, LocationIdentity locationIdentity) {
- return readShort(signed(offset), locationIdentity);
+ return readShort(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public int readInt(int offset, LocationIdentity locationIdentity) {
- return readInt(signed(offset), locationIdentity);
+ return readInt(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public long readLong(int offset, LocationIdentity locationIdentity) {
- return readLong(signed(offset), locationIdentity);
+ return readLong(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public float readFloat(int offset, LocationIdentity locationIdentity) {
- return readFloat(signed(offset), locationIdentity);
+ return readFloat(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public double readDouble(int offset, LocationIdentity locationIdentity) {
- return readDouble(signed(offset), locationIdentity);
+ return readDouble(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public <T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity) {
- return readWord(signed(offset), locationIdentity);
+ return readWord(WordFactory.signed(offset), locationIdentity);
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public Object readObject(int offset, LocationIdentity locationIdentity) {
- return readObject(signed(offset), locationIdentity);
+ return readObject(WordFactory.signed(offset), locationIdentity);
}
@Override
@@ -809,61 +814,61 @@
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeByte(int offset, byte val, LocationIdentity locationIdentity) {
- writeByte(signed(offset), val, locationIdentity);
+ writeByte(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeChar(int offset, char val, LocationIdentity locationIdentity) {
- writeChar(signed(offset), val, locationIdentity);
+ writeChar(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeShort(int offset, short val, LocationIdentity locationIdentity) {
- writeShort(signed(offset), val, locationIdentity);
+ writeShort(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeInt(int offset, int val, LocationIdentity locationIdentity) {
- writeInt(signed(offset), val, locationIdentity);
+ writeInt(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeLong(int offset, long val, LocationIdentity locationIdentity) {
- writeLong(signed(offset), val, locationIdentity);
+ writeLong(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeFloat(int offset, float val, LocationIdentity locationIdentity) {
- writeFloat(signed(offset), val, locationIdentity);
+ writeFloat(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeDouble(int offset, double val, LocationIdentity locationIdentity) {
- writeDouble(signed(offset), val, locationIdentity);
+ writeDouble(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeWord(int offset, WordBase val, LocationIdentity locationIdentity) {
- writeWord(signed(offset), val, locationIdentity);
+ writeWord(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.INITIALIZE)
public void initializeLong(int offset, long val, LocationIdentity locationIdentity) {
- initializeLong(signed(offset), val, locationIdentity);
+ initializeLong(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeObject(int offset, Object val, LocationIdentity locationIdentity) {
- writeObject(signed(offset), val, locationIdentity);
+ writeObject(WordFactory.signed(offset), val, locationIdentity);
}
@Override
@@ -924,60 +929,60 @@
@Override
@Operation(opcode = Opcode.READ_POINTER)
public byte readByte(int offset) {
- return readByte(signed(offset));
+ return readByte(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public char readChar(int offset) {
- return readChar(signed(offset));
+ return readChar(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public short readShort(int offset) {
- return readShort(signed(offset));
+ return readShort(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public int readInt(int offset) {
- return readInt(signed(offset));
+ return readInt(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public long readLong(int offset) {
- return readLong(signed(offset));
+ return readLong(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public float readFloat(int offset) {
- return readFloat(signed(offset));
+ return readFloat(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public double readDouble(int offset) {
- return readDouble(signed(offset));
+ return readDouble(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public <T extends WordBase> T readWord(int offset) {
- return readWord(signed(offset));
+ return readWord(WordFactory.signed(offset));
}
@Override
@Operation(opcode = Opcode.READ_POINTER)
public Object readObject(int offset) {
- return readObject(signed(offset));
+ return readObject(WordFactory.signed(offset));
}
@Operation(opcode = Opcode.READ_HEAP)
public Object readObject(int offset, BarrierType barrierType) {
- return readObject(signed(offset), barrierType);
+ return readObject(WordFactory.signed(offset), barrierType);
}
@Override
@@ -1073,103 +1078,103 @@
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeByte(int offset, byte val) {
- writeByte(signed(offset), val);
+ writeByte(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeChar(int offset, char val) {
- writeChar(signed(offset), val);
+ writeChar(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeShort(int offset, short val) {
- writeShort(signed(offset), val);
+ writeShort(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeInt(int offset, int val) {
- writeInt(signed(offset), val);
+ writeInt(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeLong(int offset, long val) {
- writeLong(signed(offset), val);
+ writeLong(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeFloat(int offset, float val) {
- writeFloat(signed(offset), val);
+ writeFloat(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeDouble(int offset, double val) {
- writeDouble(signed(offset), val);
+ writeDouble(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeWord(int offset, WordBase val) {
- writeWord(signed(offset), val);
+ writeWord(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.WRITE_POINTER)
public void writeObject(int offset, Object val) {
- writeObject(signed(offset), val);
+ writeObject(WordFactory.signed(offset), val);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity) {
- return compareAndSwapInt(signed(offset), expectedValue, newValue, locationIdentity);
+ return compareAndSwapInt(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity) {
- return compareAndSwapLong(signed(offset), expectedValue, newValue, locationIdentity);
+ return compareAndSwapLong(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public <T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity) {
- return compareAndSwapWord(signed(offset), expectedValue, newValue, locationIdentity);
+ return compareAndSwapWord(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity) {
- return compareAndSwapObject(signed(offset), expectedValue, newValue, locationIdentity);
+ return compareAndSwapObject(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity) {
- return logicCompareAndSwapInt(signed(offset), expectedValue, newValue, locationIdentity);
+ return logicCompareAndSwapInt(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity) {
- return logicCompareAndSwapLong(signed(offset), expectedValue, newValue, locationIdentity);
+ return logicCompareAndSwapLong(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity) {
- return logicCompareAndSwapWord(signed(offset), expectedValue, newValue, locationIdentity);
+ return logicCompareAndSwapWord(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
@Override
@Operation(opcode = Opcode.CAS_POINTER)
public boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity) {
- return logicCompareAndSwapObject(signed(offset), expectedValue, newValue, locationIdentity);
+ return logicCompareAndSwapObject(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
}
/**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
import static org.graalvm.compiler.nodes.ConstantNode.forInt;
import static org.graalvm.compiler.nodes.ConstantNode.forIntegerKind;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
import java.lang.reflect.Constructor;
import java.util.Arrays;
@@ -70,8 +70,8 @@
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.word.Word.Opcode;
import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.impl.WordFactoryOperation;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.meta.JavaKind;
@@ -85,7 +85,7 @@
* A plugin for calls to {@linkplain Operation word operations}, as well as all other nodes that
* need special handling for {@link Word} types.
*/
-public class WordOperationPlugin extends WordFactory implements NodePlugin, TypePlugin, InlineInvokePlugin {
+public class WordOperationPlugin implements NodePlugin, TypePlugin, InlineInvokePlugin {
protected final WordTypes wordTypes;
protected final JavaKind wordKind;
protected final SnippetReflectionProvider snippetReflection;
@@ -175,14 +175,14 @@
}
protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index) {
- return new LoadIndexedNode(null, array, index, wordTypes.getWordKind());
+ return new LoadIndexedNode(null, array, index, wordKind);
}
@Override
public boolean handleStoreField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field, ValueNode value) {
if (field.getJavaKind() == JavaKind.Object) {
boolean isWordField = wordTypes.isWord(field.getType());
- boolean isWordValue = value.getStackKind() == wordTypes.getWordKind();
+ boolean isWordValue = value.getStackKind() == wordKind;
if (isWordField && !isWordValue) {
throw bailout(b, "Cannot store a non-word value into a word field: " + field.format("%H.%n"));
@@ -205,20 +205,20 @@
ResolvedJavaType arrayType = StampTool.typeOrNull(array);
if (arrayType != null && wordTypes.isWord(arrayType.getComponentType())) {
assert elementKind == JavaKind.Object;
- if (value.getStackKind() != wordTypes.getWordKind()) {
+ if (value.getStackKind() != wordKind) {
throw bailout(b, "Cannot store a non-word value into a word array: " + arrayType.toJavaName(true));
}
b.add(createStoreIndexedNode(array, index, value));
return true;
}
- if (elementKind == JavaKind.Object && value.getStackKind() == wordTypes.getWordKind()) {
+ if (elementKind == JavaKind.Object && value.getStackKind() == wordKind) {
throw bailout(b, "Cannot store a word value into a non-word array: " + arrayType.toJavaName(true));
}
return false;
}
protected StoreIndexedNode createStoreIndexedNode(ValueNode array, ValueNode index, ValueNode value) {
- return new StoreIndexedNode(array, index, wordTypes.getWordKind(), value);
+ return new StoreIndexedNode(array, index, wordKind, value);
}
@Override
@@ -230,7 +230,7 @@
return false;
}
- if (object.getStackKind() != wordTypes.getWordKind()) {
+ if (object.getStackKind() != wordKind) {
throw bailout(b, "Cannot cast a non-word value to a word type: " + type.toJavaName(true));
}
b.push(JavaKind.Object, object);
@@ -249,7 +249,7 @@
protected void processWordOperation(GraphBuilderContext b, ValueNode[] args, ResolvedJavaMethod wordMethod) throws GraalError {
JavaKind returnKind = wordMethod.getSignature().getReturnKind();
- WordFactory.FactoryOperation factoryOperation = BridgeMethodUtils.getAnnotation(WordFactory.FactoryOperation.class, wordMethod);
+ WordFactoryOperation factoryOperation = BridgeMethodUtils.getAnnotation(WordFactoryOperation.class, wordMethod);
if (factoryOperation != null) {
switch (factoryOperation.opcode()) {
case ZERO:
@@ -510,10 +510,6 @@
}
}
- public WordTypes getWordTypes() {
- return wordTypes;
- }
-
private static BailoutException bailout(GraphBuilderContext b, String msg) {
throw b.bailout(msg + "\nat " + b.getCode().asStackTraceElement(b.bci()));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordTypes.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordTypes.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphElements.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphElements.java Thu Apr 26 17:59:02 2018 +0200
@@ -187,7 +187,10 @@
int nodeSourcePositionBCI(P pos);
/**
- * Stack trace element for a method, index and position.
+ * Stack trace element for a method, index and position. This is the basic version of the method
+ * that works with {@link StackTraceElement} and is suitable for Java-like languages. Should you
+ * need to provide more details about the location of multiple strata, see
+ * {@link GraphLocations} interface that gives more control over the provided location data.
*
* @param method the method
* @param bci the index
@@ -195,4 +198,5 @@
* @return stack trace element for the method, index and position
*/
StackTraceElement methodStackTraceElement(M method, int bci, P pos);
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphLocations.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.graphio;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * Provides source location information about compiled code. This interface is an extension of
+ * {@link GraphElements} - by default the elements work with classical {@link StackTraceElement}.
+ * Should the default behavior not be sufficient, feel free to implement the additional operations
+ * available in this interface and register your implementation when {@link GraphOutput.Builder
+ * building} the {@link GraphOutput} instance.
+ *
+ * @param <M> type representing methods
+ * @param <P> type representing source code location
+ * @param <L> represeting {@link StackTraceElement stack element} location
+ *
+ * @since 0.33 part of GraalVM 0.33
+ */
+public interface GraphLocations<M, P, L> {
+ /**
+ * Stack trace element for a method, index and position. Returns all applicable source locations
+ * for given code position. Each provided location is expected to represent location in a
+ * different {@link #locationLanguage(java.lang.Object) language}.
+ *
+ * @param method the method
+ * @param bci the index
+ * @param pos the position
+ * @return elements representing location for all language strata
+ */
+ Iterable<L> methodLocation(M method, int bci, P pos);
+
+ /**
+ * Identification of the language. Each location can point to a source in a different language -
+ * e.g. each location can have multiple <em>strata</em>.
+ *
+ * @param location the location
+ * @return id of the language/strata
+ */
+ String locationLanguage(L location);
+
+ /**
+ * The universal resource identification that contains the location.If the location can be found
+ * in an assummably accessible resource, then use such resource identification. It is up to the
+ * side processing the URI to load the content from the location. Protocols scheme {@code file},
+ * {@code http}, or {@code https} are assumed to be accessible.
+ * <p>
+ * If the location is inside of a virtual source, or source which is unlikely to be accessible
+ * outside of running program, then it may be better to encode the whole source into the
+ * resource identifier. This can be done by using
+ * <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs">data
+ * URIs</a> like:
+ *
+ * <pre>
+ * data:text/javascript,alert('Vivat graphs!')
+ * </pre>
+ *
+ * @param location the location
+ * @return the file name for the given location or {@code null} if it is not known
+ * @throws URISyntaxException yielding this exception aborts the graph dumping
+ */
+ URI locationURI(L location) throws URISyntaxException;
+
+ /**
+ * Line number of a location. The first line in the source file is one. Negative value means the
+ * line location isn't available. In such situation one can provide an offset driven location
+ * co-ordinates via {@link #locationOffsetStart(java.lang.Object)} and
+ * {@link #locationOffsetEnd(java.lang.Object)} methods.
+ *
+ * @param location the location
+ * @return the line number for given location, negative value means no line
+ */
+ int locationLineNumber(L location);
+
+ /**
+ * Offset of the location. In certain situations it is preferrable to specify offset rather than
+ * {@link #locationLineNumber(java.lang.Object) line number} of a location in source. In such
+ * case return the start offset from this method and end offset via
+ * {@link #locationOffsetEnd(java.lang.Object)} method. Offsets are counted from {@code 0}.
+ *
+ * @param location the location
+ * @return the starting offset of the location, negative value means no offset
+ */
+ int locationOffsetStart(L location);
+
+ /**
+ * Offset of the location. In certain situations it is preferrable to specify offset rather than
+ * {@link #locationLineNumber(java.lang.Object) line number} of a location in source. In such
+ * case return the start offset via {@link #locationOffsetStart(java.lang.Object)} method and
+ * end from this method. Offsets are counted from {@code 0}.
+ *
+ * @param location the location
+ * @return the end offset (exclusive) of the location, negative value means no offset
+ */
+ int locationOffsetEnd(L location);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,10 @@
import java.io.Closeable;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.channels.WritableByteChannel;
+import java.util.Collections;
import java.util.Map;
/**
@@ -34,9 +37,9 @@
* @param <M> the type of methods this instance handles
*/
public final class GraphOutput<G, M> implements Closeable {
- private final GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?> printer;
+ private final GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?, ?> printer;
- private GraphOutput(GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?> p) {
+ private GraphOutput(GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?, ?> p) {
this.printer = p;
}
@@ -110,7 +113,8 @@
*/
public static final class Builder<G, N, M> {
private final GraphStructure<G, N, ?, ?> structure;
- private GraphElements<M, ?, ?, ?> elements = null;
+ private ElementsAndLocations<M, ?, ?> elementsAndLocations;
+
private GraphTypes types = DefaultGraphTypes.DEFAULT;
private GraphBlocks<G, ?, N> blocks = DefaultGraphBlocks.empty();
private int major = 4;
@@ -164,9 +168,24 @@
* @param graphElements the elements implementation
* @return this builder
*/
+ public <E, P> Builder<G, N, E> elements(GraphElements<E, ?, ?, P> graphElements) {
+ StackLocations<E, P> loc = new StackLocations<>(graphElements);
+ return elementsAndLocations(graphElements, loc);
+ }
+
+ /**
+ * Associates implementation of graph elements and an advanced way to interpret their
+ * locations.
+ *
+ * @param graphElements the elements implementation
+ * @param graphLocations the locations for the elements
+ * @return this builder
+ * @since 0.33 GraalVM 0.33
+ */
@SuppressWarnings({"unchecked", "rawtypes"})
- public <E> Builder<G, N, E> elements(GraphElements<E, ?, ?, ?> graphElements) {
- this.elements = (GraphElements) graphElements;
+ public <E, P> Builder<G, N, E> elementsAndLocations(GraphElements<E, ?, ?, P> graphElements, GraphLocations<E, P, ?> graphLocations) {
+ ElementsAndLocations both = new ElementsAndLocations<>(graphElements, graphLocations);
+ this.elementsAndLocations = both;
return (Builder<G, N, E>) this;
}
@@ -179,8 +198,7 @@
* @throws IOException if something goes wrong when writing to the channel
*/
public GraphOutput<G, M> build(WritableByteChannel channel) throws IOException {
- ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(major, minor, structure, types, blocks, elements, channel);
- return new GraphOutput<>(p);
+ return buildImpl(elementsAndLocations, channel);
}
/**
@@ -200,8 +218,85 @@
* @return new output sharing {@code channel} and other internals with {@code parent}
*/
public GraphOutput<G, M> build(GraphOutput<?, ?> parent) {
- ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(parent.printer, structure, types, blocks, elements);
+ return buildImpl(elementsAndLocations, parent);
+ }
+
+ private <L, P> GraphOutput<G, M> buildImpl(ElementsAndLocations<M, L, P> e, WritableByteChannel channel) throws IOException {
+ // @formatter:off
+ ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?, ?> p = new ProtocolImpl<>(
+ major, minor, structure, types, blocks,
+ e == null ? null : e.elements,
+ e == null ? null : e.locations, channel
+ );
+ // @formatter:on
+ return new GraphOutput<>(p);
+ }
+
+ private <L, P> GraphOutput<G, M> buildImpl(ElementsAndLocations<M, L, P> e, GraphOutput<?, ?> parent) {
+ // @formatter:off
+ ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?, ?> p = new ProtocolImpl<>(
+ parent.printer, structure, types, blocks,
+ e == null ? null : e.elements,
+ e == null ? null : e.locations
+ );
+ // @formatter:on
return new GraphOutput<>(p);
}
}
+
+ private static final class ElementsAndLocations<M, P, L> {
+ final GraphElements<M, ?, ?, P> elements;
+ final GraphLocations<M, P, L> locations;
+
+ ElementsAndLocations(GraphElements<M, ?, ?, P> elements, GraphLocations<M, P, L> locations) {
+ elements.getClass();
+ locations.getClass();
+ this.elements = elements;
+ this.locations = locations;
+ }
+ }
+
+ private static final class StackLocations<M, P> implements GraphLocations<M, P, StackTraceElement> {
+ private final GraphElements<M, ?, ?, P> graphElements;
+
+ StackLocations(GraphElements<M, ?, ?, P> graphElements) {
+ this.graphElements = graphElements;
+ }
+
+ @Override
+ public Iterable<StackTraceElement> methodLocation(M method, int bci, P pos) {
+ StackTraceElement ste = this.graphElements.methodStackTraceElement(method, bci, pos);
+ return Collections.singleton(ste);
+ }
+
+ @Override
+ public URI locationURI(StackTraceElement location) {
+ String path = location.getFileName();
+ try {
+ return path == null ? null : new URI(null, null, path, null);
+ } catch (URISyntaxException ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ @Override
+ public int locationLineNumber(StackTraceElement location) {
+ return location.getLineNumber();
+ }
+
+ @Override
+ public String locationLanguage(StackTraceElement location) {
+ return "Java";
+ }
+
+ @Override
+ public int locationOffsetStart(StackTraceElement location) {
+ return -1;
+ }
+
+ @Override
+ public int locationOffsetEnd(StackTraceElement location) {
+ return -1;
+ }
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,16 +24,20 @@
import java.io.Closeable;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.Objects;
-abstract class GraphProtocol<Graph, Node, NodeClass, Edges, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> implements Closeable {
+abstract class GraphProtocol<Graph, Node, NodeClass, Edges, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition, Location> implements Closeable {
private static final Charset UTF8 = Charset.forName("UTF-8");
private static final int CONSTANT_POOL_MAX_SIZE = 8000;
@@ -76,7 +80,7 @@
final int versionMinor;
GraphProtocol(WritableByteChannel channel, int major, int minor) throws IOException {
- if (major > 5 || (major == 5 && minor > 0)) {
+ if (major > 6 || (major == 6 && minor > 0)) {
throw new IllegalArgumentException("Unrecognized version " + major + "." + minor);
}
this.versionMajor = major;
@@ -87,7 +91,7 @@
writeVersion();
}
- GraphProtocol(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?> parent) {
+ GraphProtocol(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?, ?> parent) {
this.versionMajor = parent.versionMajor;
this.versionMinor = parent.versionMinor;
this.constantPool = parent.constantPool;
@@ -254,7 +258,19 @@
protected abstract int findNodeSourcePositionBCI(NodeSourcePosition pos);
- protected abstract StackTraceElement findMethodStackTraceElement(ResolvedJavaMethod method, int bci, NodeSourcePosition pos);
+ protected abstract Iterable<Location> findLocation(ResolvedJavaMethod method, int bci, NodeSourcePosition pos);
+
+ protected abstract String findLocationFile(Location loc) throws IOException;
+
+ protected abstract int findLocationLine(Location loc);
+
+ protected abstract URI findLocationURI(Location loc) throws URISyntaxException;
+
+ protected abstract String findLocationLanguage(Location loc);
+
+ protected abstract int findLocationStart(Location loc);
+
+ protected abstract int findLocationEnd(Location loc);
private void writeVersion() throws IOException {
writeBytesRaw(MAGIC_BYTES);
@@ -374,34 +390,57 @@
if (id == null) {
addPoolEntry(object);
} else {
- if (findJavaField(object) != null) {
- writeByte(POOL_FIELD);
- } else if (findSignature(object) != null) {
- writeByte(POOL_SIGNATURE);
- } else if (versionMajor >= 4 && findNodeSourcePosition(object) != null) {
- writeByte(POOL_NODE_SOURCE_POSITION);
- } else {
- final Node node = findNode(object);
- if (versionMajor == 4 && node != null) {
- object = classForNode(node);
+ int type = findPoolType(object, null);
+ writeByte(type);
+ writeShort(id.charValue());
+ }
+ }
+
+ private int findPoolType(Object obj, Object[] found) throws IOException {
+ Object object = obj;
+ if (object == null) {
+ return POOL_NULL;
+ }
+ if (isFound(findJavaField(object), found)) {
+ return POOL_FIELD;
+ } else if (isFound(findSignature(object), found)) {
+ return POOL_SIGNATURE;
+ } else if (versionMajor >= 4 && isFound(findNodeSourcePosition(object), found)) {
+ return POOL_NODE_SOURCE_POSITION;
+ } else {
+ final Node node = findNode(object);
+ if (versionMajor == 4 && node != null) {
+ object = classForNode(node);
+ }
+ if (isFound(findNodeClass(object), found)) {
+ return POOL_NODE_CLASS;
+ } else if (versionMajor >= 5 && isFound(node, found)) {
+ return POOL_NODE;
+ } else if (isFound(findMethod(object), found)) {
+ return POOL_METHOD;
+ } else if (object instanceof Enum<?>) {
+ if (found != null) {
+ found[0] = ((Enum<?>) object).ordinal();
}
- if (findNodeClass(object) != null) {
- writeByte(POOL_NODE_CLASS);
- } else if (versionMajor >= 5 && node != null) {
- writeByte(POOL_NODE);
- } else if (findMethod(object) != null) {
- writeByte(POOL_METHOD);
+ return POOL_ENUM;
+ } else {
+ int val = findEnumOrdinal(object);
+ if (val >= 0) {
+ if (found != null) {
+ found[0] = val;
+ }
+ return POOL_ENUM;
+ } else if (object instanceof Class<?>) {
+ if (found != null) {
+ found[0] = ((Class<?>) object).getName();
+ }
+ return POOL_CLASS;
+ } else if (isFound(findJavaTypeName(object), found)) {
+ return POOL_CLASS;
} else {
- if (object instanceof Enum<?> || findEnumOrdinal(object) >= 0) {
- writeByte(POOL_ENUM);
- } else if (object instanceof Class<?> || findJavaTypeName(object) != null) {
- writeByte(POOL_CLASS);
- } else {
- writeByte(POOL_STRING);
- }
+ return POOL_STRING;
}
}
- writeShort(id.charValue());
}
}
@@ -519,61 +558,89 @@
}
}
- @SuppressWarnings("all")
+ @SuppressWarnings("unchecked")
private void addPoolEntry(Object obj) throws IOException {
Object object = obj;
- ResolvedJavaField field;
- String typeName;
- Signature signature;
- NodeSourcePosition pos;
- int enumOrdinal;
char index = constantPool.add(object);
writeByte(POOL_NEW);
writeShort(index);
- if ((field = findJavaField(object)) != null) {
- writeByte(POOL_FIELD);
- writePoolObject(findFieldDeclaringClass(field));
- writePoolObject(findFieldName(field));
- writePoolObject(findFieldTypeName(field));
- writeInt(findFieldModifiers(field));
- } else if ((signature = findSignature(object)) != null) {
- writeByte(POOL_SIGNATURE);
- int args = findSignatureParameterCount(signature);
- writeShort((char) args);
- for (int i = 0; i < args; i++) {
- writePoolObject(findSignatureParameterTypeName(signature, i));
+
+ Object[] found = {null};
+ int type = findPoolType(object, found);
+ writeByte(type);
+ switch (type) {
+ case POOL_FIELD: {
+ ResolvedJavaField field = (ResolvedJavaField) found[0];
+ Objects.nonNull(field);
+ writePoolObject(findFieldDeclaringClass(field));
+ writePoolObject(findFieldName(field));
+ writePoolObject(findFieldTypeName(field));
+ writeInt(findFieldModifiers(field));
+ break;
+ }
+ case POOL_SIGNATURE: {
+ Signature signature = (Signature) found[0];
+ int args = findSignatureParameterCount(signature);
+ writeShort((char) args);
+ for (int i = 0; i < args; i++) {
+ writePoolObject(findSignatureParameterTypeName(signature, i));
+ }
+ writePoolObject(findSignatureReturnTypeName(signature));
+ break;
}
- writePoolObject(findSignatureReturnTypeName(signature));
- } else if (versionMajor >= 4 && (pos = findNodeSourcePosition(object)) != null) {
- writeByte(POOL_NODE_SOURCE_POSITION);
- ResolvedJavaMethod method = findNodeSourcePositionMethod(pos);
- writePoolObject(method);
- final int bci = findNodeSourcePositionBCI(pos);
- writeInt(bci);
- StackTraceElement ste = findMethodStackTraceElement(method, bci, pos);
- if (ste != null && ste.getFileName() != null) {
- writePoolObject(ste.getFileName());
- writeInt(ste.getLineNumber());
- } else {
- writePoolObject(null);
+ case POOL_NODE_SOURCE_POSITION: {
+ NodeSourcePosition pos = (NodeSourcePosition) found[0];
+ Objects.nonNull(pos);
+ ResolvedJavaMethod method = findNodeSourcePositionMethod(pos);
+ writePoolObject(method);
+ final int bci = findNodeSourcePositionBCI(pos);
+ writeInt(bci);
+ Iterator<Location> ste = findLocation(method, bci, pos).iterator();
+ if (versionMajor >= 6) {
+ while (ste.hasNext()) {
+ Location loc = ste.next();
+ URI uri;
+ try {
+ uri = findLocationURI(loc);
+ } catch (URISyntaxException ex) {
+ throw new IOException(ex);
+ }
+ if (uri == null) {
+ throw new IOException("No URI for " + loc);
+ }
+ String l = findLocationLanguage(loc);
+ if (l == null) {
+ continue;
+ }
+ writePoolObject(uri.toString());
+ writeString(l);
+ writeInt(findLocationLine(loc));
+ writeInt(findLocationStart(loc));
+ writeInt(findLocationEnd(loc));
+ }
+ writePoolObject(null);
+ } else {
+ Location first = ste.hasNext() ? ste.next() : null;
+ String fileName = first != null ? findLocationFile(first) : null;
+ if (fileName != null) {
+ writePoolObject(fileName);
+ writeInt(findLocationLine(first));
+ } else {
+ writePoolObject(null);
+ }
+ }
+ writePoolObject(findNodeSourcePositionCaller(pos));
+ break;
}
- writePoolObject(findNodeSourcePositionCaller(pos));
- } else {
- Node node = findNode(object);
- if (node != null) {
- if (versionMajor >= 5) {
- writeByte(POOL_NODE);
- writeInt(findNodeId(node));
- writePoolObject(classForNode(node));
- return;
- }
- if (versionMajor == 4) {
- object = classForNode(node);
- }
+ case POOL_NODE: {
+ Node node = (Node) found[0];
+ Objects.nonNull(node);
+ writeInt(findNodeId(node));
+ writePoolObject(classForNode(node));
+ break;
}
- NodeClass nodeClass = findNodeClass(object);
- if (nodeClass != null) {
- writeByte(POOL_NODE_CLASS);
+ case POOL_NODE_CLASS: {
+ NodeClass nodeClass = (NodeClass) found[0];
final Object clazz = findJavaClass(nodeClass);
if (versionMajor >= 3) {
writePoolObject(clazz);
@@ -585,39 +652,50 @@
}
writeEdgesInfo(nodeClass, true);
writeEdgesInfo(nodeClass, false);
- return;
+ break;
}
- ResolvedJavaMethod method = findMethod(object);
- if (method == null) {
- if ((typeName = findJavaTypeName(object)) != null) {
- writeByte(POOL_CLASS);
- writeString(typeName);
- String[] enumValueNames = findEnumTypeValues(object);
- if (enumValueNames != null) {
- writeByte(ENUM_KLASS);
- writeInt(enumValueNames.length);
- for (String o : enumValueNames) {
- writePoolObject(o);
- }
- } else {
- writeByte(KLASS);
+ case POOL_CLASS: {
+ String typeName = (String) found[0];
+ Objects.nonNull(typeName);
+ writeString(typeName);
+ String[] enumValueNames = findEnumTypeValues(object);
+ if (enumValueNames != null) {
+ writeByte(ENUM_KLASS);
+ writeInt(enumValueNames.length);
+ for (String o : enumValueNames) {
+ writePoolObject(o);
}
- } else if ((enumOrdinal = findEnumOrdinal(object)) >= 0) {
- writeByte(POOL_ENUM);
- writePoolObject(findEnumClass(object));
- writeInt(enumOrdinal);
} else {
- writeByte(POOL_STRING);
- writeString(object.toString());
+ writeByte(KLASS);
+ }
+ break;
+ }
+ case POOL_METHOD: {
+ ResolvedJavaMethod method = (ResolvedJavaMethod) found[0];
+ Objects.nonNull(method);
+ writePoolObject(findMethodDeclaringClass(method));
+ writePoolObject(findMethodName(method));
+ final Signature methodSignature = findMethodSignature(method);
+ if (findSignature(methodSignature) == null) {
+ throw new IOException("Should be recognized as signature: " + methodSignature + " for " + method);
}
- return;
+ writePoolObject(methodSignature);
+ writeInt(findMethodModifiers(method));
+ writeBytes(findMethodCode(method));
+ break;
}
- writeByte(POOL_METHOD);
- writePoolObject(findMethodDeclaringClass(method));
- writePoolObject(findMethodName(method));
- writePoolObject(findMethodSignature(method));
- writeInt(findMethodModifiers(method));
- writeBytes(findMethodCode(method));
+ case POOL_ENUM: {
+ int enumOrdinal = (int) found[0];
+ writePoolObject(findEnumClass(object));
+ writeInt(enumOrdinal);
+ break;
+ }
+ case POOL_STRING: {
+ writeString(object.toString());
+ break;
+ }
+ default:
+ throw new IllegalStateException();
}
}
@@ -696,6 +774,16 @@
}
}
+ private static boolean isFound(Object obj, Object[] found) {
+ if (obj == null) {
+ return false;
+ }
+ if (found != null) {
+ found[0] = obj;
+ }
+ return true;
+ }
+
private static final class ConstantPool extends LinkedHashMap<Object, Character> {
private final LinkedList<Character> availableIds;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -22,34 +22,43 @@
*/
package org.graalvm.graphio;
+import java.io.File;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.channels.WritableByteChannel;
import java.util.Collection;
import java.util.Map;
-final class ProtocolImpl<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition>
- extends GraphProtocol<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> {
+final class ProtocolImpl<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition, Location>
+ extends GraphProtocol<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition, Location> {
private final GraphStructure<Graph, Node, NodeClass, Port> structure;
private final GraphTypes types;
private final GraphBlocks<Graph, Block, Node> blocks;
private final GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements;
+ private final GraphLocations<ResolvedJavaMethod, NodeSourcePosition, Location> locations;
ProtocolImpl(int major, int minor, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
- GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements, WritableByteChannel channel) throws IOException {
+ GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements,
+ GraphLocations<ResolvedJavaMethod, NodeSourcePosition, Location> locs,
+ WritableByteChannel channel) throws IOException {
super(channel, major, minor);
this.structure = structure;
this.types = enums;
this.blocks = blocks;
this.elements = elements;
+ this.locations = locs;
}
- ProtocolImpl(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?> parent, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
- GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements) {
+ ProtocolImpl(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?, ?> parent, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
+ GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements,
+ GraphLocations<ResolvedJavaMethod, NodeSourcePosition, Location> locs) {
super(parent);
this.structure = structure;
this.types = enums;
this.blocks = blocks;
this.elements = elements;
+ this.locations = locs;
}
@Override
@@ -285,8 +294,56 @@
}
@Override
- protected StackTraceElement findMethodStackTraceElement(ResolvedJavaMethod method, int bci, NodeSourcePosition pos) {
- return elements.methodStackTraceElement(method, bci, pos);
+ protected Iterable<Location> findLocation(ResolvedJavaMethod method, int bci, NodeSourcePosition pos) {
+ return locations.methodLocation(method, bci, pos);
+ }
+
+ @Override
+ protected String findLocationFile(Location loc) throws IOException {
+ if (loc == null) {
+ return null;
+ }
+ URI u;
+ try {
+ u = locations.locationURI(loc);
+ } catch (URISyntaxException ex) {
+ throw new IOException(ex);
+ }
+ if (u == null) {
+ return null;
+ }
+ if (u.getScheme() == null) {
+ return u.getPath();
+ }
+ if ("file".equals(u.getScheme())) {
+ return new File(u).getPath();
+ }
+ return null;
+ }
+
+ @Override
+ protected int findLocationLine(Location loc) {
+ return locations.locationLineNumber(loc);
+ }
+
+ @Override
+ protected URI findLocationURI(Location loc) throws URISyntaxException {
+ return locations.locationURI(loc);
+ }
+
+ @Override
+ protected String findLocationLanguage(Location loc) {
+ return locations.locationLanguage(loc);
+ }
+
+ @Override
+ protected int findLocationStart(Location loc) {
+ return locations.locationOffsetStart(loc);
+ }
+
+ @Override
+ protected int findLocationEnd(Location loc) {
+ return locations.locationOffsetEnd(loc);
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,8 +24,8 @@
import static org.junit.Assert.assertEquals;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.test.GraalTest;
import org.graalvm.util.ObjectSizeEstimate;
import org.junit.Assume;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
import java.lang.reflect.Modifier;
import java.util.ArrayList;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
/**
* Calculates approximate estimates of the size of an object graph.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
- This configuration file was written by the eclipse-cs plugin configuration editor
--->
-<!--
- Checkstyle-Configuration: Checks
- Description: none
--->
-<module name="Checker">
- <property name="severity" value="error"/>
- <module name="TreeWalker">
- <module name="AvoidStarImport">
- <property name="allowClassImports" value="false"/>
- <property name="allowStaticMemberImports" value="false"/>
- </module>
- <property name="tabWidth" value="4"/>
- <module name="FileContentsHolder"/>
- <module name="JavadocStyle">
- <property name="checkHtml" value="false"/>
- </module>
- <module name="LocalFinalVariableName"/>
- <module name="LocalVariableName"/>
- <module name="MemberName">
- <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
- </module>
- <module name="MethodName"/>
- <module name="PackageName"/>
- <module name="ParameterName"/>
- <module name="TypeName">
- <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
- </module>
- <module name="RedundantImport"/>
- <module name="LineLength">
- <property name="max" value="250"/>
- </module>
- <module name="MethodParamPad"/>
- <module name="NoWhitespaceAfter">
- <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
- </module>
- <module name="NoWhitespaceBefore">
- <property name="tokens" value="SEMI,POST_DEC,POST_INC"/>
- </module>
- <module name="ParenPad"/>
- <module name="TypecastParenPad">
- <property name="tokens" value="RPAREN,TYPECAST"/>
- </module>
- <module name="WhitespaceAfter"/>
- <module name="WhitespaceAround">
- <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
- </module>
- <module name="RedundantModifier"/>
- <module name="AvoidNestedBlocks">
- <property name="allowInSwitchCase" value="true"/>
- </module>
- <module name="EmptyBlock">
- <property name="option" value="text"/>
- <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
- </module>
- <module name="LeftCurly"/>
- <module name="NeedBraces"/>
- <module name="RightCurly"/>
- <module name="EmptyStatement"/>
- <module name="HiddenField">
- <property name="severity" value="ignore"/>
- <property name="ignoreConstructorParameter" value="true"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="FinalClass"/>
- <module name="HideUtilityClassConstructor">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="ArrayTypeStyle"/>
- <module name="UpperEll"/>
- <module name="FallThrough"/>
- <module name="FinalLocalVariable">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="MultipleVariableDeclarations"/>
- <module name="StringLiteralEquality">
- <property name="severity" value="error"/>
- </module>
- <module name="SuperFinalize"/>
- <module name="UnnecessaryParentheses">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="Indentation">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="StaticVariableName">
- <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
- </module>
- <module name="EmptyForInitializerPad"/>
- <module name="EmptyForIteratorPad"/>
- <module name="ModifierOrder"/>
- <module name="DefaultComesLast"/>
- <module name="InnerAssignment">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="ModifiedControlVariable"/>
- <module name="MutableException">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="ParameterAssignment">
- <property name="severity" value="ignore"/>
- <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
- </module>
- <module name="RegexpSinglelineJava">
- <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
- <property name="format" value="\s$"/>
- <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
- <property name="ignoreComments" value="true"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
- </module>
- <module name="RegexpSinglelineJava">
- <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
- <property name="format" value=" ,"/>
- <property name="message" value="illegal space before a comma"/>
- <property name="ignoreComments" value="true"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="[^\x00-\x7F]"/>
- <property name="message" value="Only use ASCII characters."/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
- <property name="message" value="Don't use old synchronized collection classes"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="instanceof MoveOp"/>
- <property name="message" value="Do not use `op instanceof MoveOp`. Use `MoveOp.isMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="instanceof ValueMoveOp"/>
- <property name="message" value="Do not use `op instanceof ValueMoveOp`. Use `ValueMoveOp.isValueMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="instanceof LoadConstantOp"/>
- <property name="message" value="Do not use `op instanceof LoadConstantOp`. Use `LoadConstantOp.isLoadConstantOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="\(MoveOp\)"/>
- <property name="message" value="Do not cast directly to `MoveOp`. Use `MoveOp.asMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="\(ValueMoveOp\)"/>
- <property name="message" value="Do not cast directly to `ValueMoveOp`. Use `ValueMoveOp.asValueMoveOp(op)` instead!"/>
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="\(LoadConstantOp\)"/>
- <property name="message" value="Do not cast directly to `LoadConstantOp`. Use `LoadConstantOp.asLoadConstantOp(op)` instead!"/>
- </module>
- </module>
- <module name="RegexpHeader">
- <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation. Oracle designates this\n \* particular file as subject to the "Classpath" exception as provided\n \* by Oracle in the LICENSE file that accompanied this code.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
- <property name="fileExtensions" value="java"/>
- </module>
- <module name="FileTabCharacter">
- <property name="severity" value="error"/>
- <property name="fileExtensions" value="java"/>
- </module>
- <module name="NewlineAtEndOfFile">
- <property name="lineSeparator" value="lf"/>
- </module>
- <module name="Translation"/>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
- <property name="checkFormat" value="ConstantNameCheck"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
- <property name="checkFormat" value="MethodName"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
- <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
- <property name="checkFormat" value="ParameterAssignment"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
- <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
- <property name="checkFormat" value="FinalLocalVariable"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop"/>
- <property name="onCommentFormat" value="Checkstyle: resume"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
- <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
- <property name="checkFormat" value="InnerAssignment"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
- <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
- <property name="checkFormat" value="MemberName"/>
- <property name="checkC" value="false"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
- </module>
- <module name="RegexpMultiline">
- <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
- <property name="format" value="\r\n"/>
- <property name="message" value="illegal Windows line ending"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop header check"/>
- <property name="onCommentFormat" value="CheckStyle: resume header check"/>
- <property name="checkFormat" value=".*Header"/>
- <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
- <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
- <property name="checkFormat" value="LineLength"/>
- </module>
- <module name="SuppressionCommentFilter">
- <property name="offCommentFormat" value="CheckStyle: start generated"/>
- <property name="onCommentFormat" value="CheckStyle: stop generated"/>
- <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
- </module>
-</module>
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/ComparableWord.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-public interface ComparableWord extends WordBase {
-
- /**
- * Compares this word with the specified value.
- *
- * @param val value to which this word is to be compared.
- * @return {@code this == val}
- */
- boolean equal(ComparableWord val);
-
- /**
- * Compares this word with the specified value.
- *
- * @param val value to which this word is to be compared.
- * @return {@code this != val}
- */
- boolean notEqual(ComparableWord val);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/LocationIdentity.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-// JaCoCo Exclude
-
-/**
- * Marker interface for location identities. A different location identity of two memory accesses
- * guarantees that the two accesses do not interfere.
- *
- * Clients of {@link LocationIdentity} must use {@link #equals(Object)}, not {@code ==}, when
- * comparing two {@link LocationIdentity} values for equality. Likewise, they must not use
- * {@link java.util.IdentityHashMap}s with {@link LocationIdentity} values as keys.
- */
-public abstract class LocationIdentity {
-
- private static final class AnyLocationIdentity extends LocationIdentity {
- @Override
- public boolean isImmutable() {
- return false;
- }
-
- @Override
- public String toString() {
- return "ANY_LOCATION";
- }
- }
-
- private static final class InitLocationIdentity extends LocationIdentity {
- @Override
- public boolean isImmutable() {
- return true;
- }
-
- @Override
- public String toString() {
- return "INIT_LOCATION";
- }
- }
-
- public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity();
- public static final LocationIdentity INIT_LOCATION = new InitLocationIdentity();
-
- /**
- * Indicates that the given location is the union of all possible mutable locations. A write to
- * such a location kill all reads from mutable locations and a read from this location is killed
- * by any write (except for initialization writes).
- */
- public static LocationIdentity any() {
- return ANY_LOCATION;
- }
-
- /**
- * Location only allowed to be used for writes. Indicates that a completely new memory location
- * 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.
- */
- public static LocationIdentity init() {
- return INIT_LOCATION;
- }
-
- /**
- * Denotes a location is unchanging in all cases. Not that this is different than the Java
- * notion of final which only requires definite assignment.
- */
- public abstract boolean isImmutable();
-
- public final boolean isMutable() {
- return !isImmutable();
- }
-
- public final boolean isAny() {
- return this == ANY_LOCATION;
- }
-
- public final boolean isInit() {
- return this == INIT_LOCATION;
- }
-
- public final boolean isSingle() {
- return this != ANY_LOCATION;
- }
-
- public final boolean overlaps(LocationIdentity other) {
- return isAny() || other.isAny() || this.equals(other);
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Pointer.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,965 +0,0 @@
-/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-/**
- * Lowest-level memory access of native C memory.
- * <p>
- * Do not use these methods to access Java objects. These methods access the raw memory without any
- * null checks, read- or write barriers. Even when the VM uses compressed pointers, then readObject
- * and writeObject methods access uncompressed pointers.
- */
-public interface Pointer extends UnsignedWord, PointerBase {
-
- /**
- * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
- * checks are performed. The caller must ensure that the Pointer contains a valid Java object
- * that can i.e., processed by the garbage collector.
- *
- * @return this Pointer cast to Object.
- */
- Object toObject();
-
- /**
- * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
- * checks are performed. The caller must ensure that the Pointer contains a valid Java object
- * that can i.e., processed by the garbage collector and the Pointer does not contain 0.
- *
- * @return this Pointer cast to non-null Object.
- */
- Object toObjectNonNull();
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- byte readByte(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- char readChar(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- short readShort(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- int readInt(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- long readLong(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- float readFloat(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- double readDouble(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- <T extends WordBase> T readWord(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- Object readObject(WordBase offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- byte readByte(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- char readChar(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- short readShort(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- int readInt(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- long readLong(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- float readFloat(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- double readDouble(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- <T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the read
- * @return the result of the memory access
- */
- Object readObject(int offset, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeChar(WordBase offset, char val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeShort(WordBase offset, short val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeInt(WordBase offset, int val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeLong(WordBase offset, long val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
-
- /**
- * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
- * are in bytes. The memory must be uninitialized or zero prior to this operation.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeByte(int offset, byte val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeChar(int offset, char val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeShort(int offset, short val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeInt(int offset, int val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeLong(int offset, long val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeFloat(int offset, float val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeDouble(int offset, double val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
-
- /**
- * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
- * are in bytes. The memory must be uninitialized or zero prior to this operation.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void initializeLong(int offset, long val, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param locationIdentity the identity of the write
- * @param val the value to be written to memory
- */
- void writeObject(int offset, Object val, LocationIdentity locationIdentity);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- byte readByte(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- char readChar(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- short readShort(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- int readInt(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- long readLong(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- float readFloat(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- double readDouble(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- <T extends WordBase> T readWord(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- Object readObject(WordBase offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- byte readByte(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- char readChar(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- short readShort(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- int readInt(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- long readLong(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- float readFloat(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- double readDouble(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- <T extends WordBase> T readWord(int offset);
-
- /**
- * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @return the result of the memory access
- */
- Object readObject(int offset);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeByte(WordBase offset, byte val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeChar(WordBase offset, char val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeShort(WordBase offset, short val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeInt(WordBase offset, int val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeLong(WordBase offset, long val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeFloat(WordBase offset, float val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeDouble(WordBase offset, double val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeWord(WordBase offset, WordBase val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- * <p>
- * The offset is always treated as a {@link SignedWord} value. However, the static type is
- * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
- * knows that the highest-order bit of the unsigned value is never used).
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeObject(WordBase offset, Object val);
-
- int compareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
- long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
- <T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
-
- Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapWord(WordBase offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeByte(int offset, byte val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeChar(int offset, char val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeShort(int offset, short val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeInt(int offset, int val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeLong(int offset, long val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeFloat(int offset, float val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeDouble(int offset, double val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeWord(int offset, WordBase val);
-
- /**
- * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
- * bytes.
- *
- * @param offset the signed offset for the memory access
- * @param val the value to be written to memory
- */
- void writeObject(int offset, Object val);
-
- int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
- long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
- <T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
-
- Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
-
- boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
- // Math functions that are defined in Unsigned, but known to preserve the
- // pointer-characteristics.
- // It is therefore safe that they return a static type of Pointer instead of Unsigned.
-
- @Override
- Pointer add(UnsignedWord val);
-
- @Override
- Pointer add(int val);
-
- @Override
- Pointer subtract(UnsignedWord val);
-
- @Override
- Pointer subtract(int val);
-
- @Override
- Pointer and(UnsignedWord val);
-
- @Override
- Pointer and(int val);
-
- @Override
- Pointer or(UnsignedWord val);
-
- @Override
- Pointer or(int val);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerBase.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-/**
- * 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}).
- */
-public interface PointerBase extends ComparableWord {
-
- /**
- * Returns true if this pointer is the {@link WordFactory#nullPointer null pointer}.
- */
- boolean isNull();
-
- /**
- * Returns true if this pointer is not the {@link WordFactory#nullPointer null pointer}.
- */
- boolean isNonNull();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/SignedWord.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-public interface SignedWord extends ComparableWord {
-
- /**
- * Returns a Signed whose value is {@code (this + val)}.
- *
- * @param val value to be added to this Signed.
- * @return {@code this + val}
- */
- SignedWord add(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this - val)}.
- *
- * @param val value to be subtracted from this Signed.
- * @return {@code this - val}
- */
- SignedWord subtract(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this * val)}.
- *
- * @param val value to be multiplied by this Signed.
- * @return {@code this * val}
- */
- SignedWord multiply(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this / val)}.
- *
- * @param val value by which this Signed is to be divided.
- * @return {@code this / val}
- */
- SignedWord signedDivide(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this % val)}.
- *
- * @param val value by which this Signed is to be divided, and the remainder computed.
- * @return {@code this % val}
- */
- SignedWord signedRemainder(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this << n)}.
- *
- * @param n shift distance, in bits.
- * @return {@code this << n}
- */
- SignedWord shiftLeft(UnsignedWord n);
-
- /**
- * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
- *
- * @param n shift distance, in bits.
- * @return {@code this >> n}
- */
- SignedWord signedShiftRight(UnsignedWord n);
-
- /**
- * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
- * if and only if this and val are both negative.)
- *
- * @param val value to be AND'ed with this Signed.
- * @return {@code this & val}
- */
- SignedWord and(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
- * if and only if either this or val is negative.)
- *
- * @param val value to be OR'ed with this Signed.
- * @return {@code this | val}
- */
- SignedWord or(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
- * if and only if exactly one of this and val are negative.)
- *
- * @param val value to be XOR'ed with this Signed.
- * @return {@code this ^ val}
- */
- SignedWord xor(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (~this)}. (This method returns a negative value if and
- * only if this Signed is non-negative.)
- *
- * @return {@code ~this}
- */
- SignedWord not();
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this == val}
- */
- boolean equal(SignedWord val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this != val}
- */
- boolean notEqual(SignedWord val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this < val}
- */
- boolean lessThan(SignedWord val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this <= val}
- */
- boolean lessOrEqual(SignedWord val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this > val}
- */
- boolean greaterThan(SignedWord val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this >= val}
- */
- boolean greaterOrEqual(SignedWord val);
-
- /**
- * Returns a Signed whose value is {@code (this + val)}.
- *
- * @param val value to be added to this Signed.
- * @return {@code this + val}
- */
- SignedWord add(int val);
-
- /**
- * Returns a Signed whose value is {@code (this - val)}.
- *
- * @param val value to be subtracted from this Signed.
- * @return {@code this - val}
- */
- SignedWord subtract(int val);
-
- /**
- * Returns a Signed whose value is {@code (this * val)}.
- *
- * @param val value to be multiplied by this Signed.
- * @return {@code this * val}
- */
- SignedWord multiply(int val);
-
- /**
- * Returns a Signed whose value is {@code (this / val)}.
- *
- * @param val value by which this Signed is to be divided.
- * @return {@code this / val}
- */
- SignedWord signedDivide(int val);
-
- /**
- * Returns a Signed whose value is {@code (this % val)}.
- *
- * @param val value by which this Signed is to be divided, and the remainder computed.
- * @return {@code this % val}
- */
- SignedWord signedRemainder(int val);
-
- /**
- * Returns a Signed whose value is {@code (this << n)}.
- *
- * @param n shift distance, in bits.
- * @return {@code this << n}
- */
- SignedWord shiftLeft(int n);
-
- /**
- * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
- *
- * @param n shift distance, in bits.
- * @return {@code this >> n}
- */
- SignedWord signedShiftRight(int n);
-
- /**
- * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
- * if and only if this and val are both negative.)
- *
- * @param val value to be AND'ed with this Signed.
- * @return {@code this & val}
- */
- SignedWord and(int val);
-
- /**
- * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
- * if and only if either this or val is negative.)
- *
- * @param val value to be OR'ed with this Signed.
- * @return {@code this | val}
- */
- SignedWord or(int val);
-
- /**
- * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
- * if and only if exactly one of this and val are negative.)
- *
- * @param val value to be XOR'ed with this Signed.
- * @return {@code this ^ val}
- */
- SignedWord xor(int val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this == val}
- */
- boolean equal(int val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this != val}
- */
- boolean notEqual(int val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this < val}
- */
- boolean lessThan(int val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this <= val}
- */
- boolean lessOrEqual(int val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this > val}
- */
- boolean greaterThan(int val);
-
- /**
- * Compares this Signed with the specified value.
- *
- * @param val value to which this Signed is to be compared.
- * @return {@code this >= val}
- */
- boolean greaterOrEqual(int val);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/UnsignedWord.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-public interface UnsignedWord extends ComparableWord {
-
- /**
- * Returns a Unsigned whose value is {@code (this + val)}.
- *
- * @param val value to be added to this Unsigned.
- * @return {@code this + val}
- */
- UnsignedWord add(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this - val)}.
- *
- * @param val value to be subtracted from this Unsigned.
- * @return {@code this - val}
- */
- UnsignedWord subtract(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this * val)}.
- *
- * @param val value to be multiplied by this Unsigned.
- * @return {@code this * val}
- */
- UnsignedWord multiply(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this / val)}.
- *
- * @param val value by which this Unsigned is to be divided.
- * @return {@code this / val}
- */
- UnsignedWord unsignedDivide(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this % val)}.
- *
- * @param val value by which this Unsigned is to be divided, and the remainder computed.
- * @return {@code this % val}
- */
- UnsignedWord unsignedRemainder(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this << n)}.
- *
- * @param n shift distance, in bits.
- * @return {@code this << n}
- */
- UnsignedWord shiftLeft(UnsignedWord n);
-
- /**
- * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
- *
- * @param n shift distance, in bits.
- * @return {@code this >> n}
- */
- UnsignedWord unsignedShiftRight(UnsignedWord n);
-
- /**
- * Returns a Unsigned whose value is {@code (this & val)}.
- *
- * @param val value to be AND'ed with this Unsigned.
- * @return {@code this & val}
- */
- UnsignedWord and(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this | val)}.
- *
- * @param val value to be OR'ed with this Unsigned.
- * @return {@code this | val}
- */
- UnsignedWord or(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this ^ val)}.
- *
- * @param val value to be XOR'ed with this Unsigned.
- * @return {@code this ^ val}
- */
- UnsignedWord xor(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (~this)}.
- *
- * @return {@code ~this}
- */
- UnsignedWord not();
-
- /**
- * Compares this Unsigned with the specified value.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this == val}
- */
- boolean equal(UnsignedWord val);
-
- /**
- * Compares this Unsigned with the specified value.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this != val}
- */
- boolean notEqual(UnsignedWord val);
-
- /**
- * Compares this Unsigned with the specified value.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this < val}
- */
- boolean belowThan(UnsignedWord val);
-
- /**
- * Compares this Unsigned with the specified value.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this <= val}
- */
- boolean belowOrEqual(UnsignedWord val);
-
- /**
- * Compares this Unsigned with the specified value.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this > val}
- */
- boolean aboveThan(UnsignedWord val);
-
- /**
- * Compares this Unsigned with the specified value.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this >= val}
- */
- boolean aboveOrEqual(UnsignedWord val);
-
- /**
- * Returns a Unsigned whose value is {@code (this + val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to be added to this Unsigned.
- * @return {@code this + val}
- */
- UnsignedWord add(int val);
-
- /**
- * Returns a Unsigned whose value is {@code (this - val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to be subtracted from this Unsigned.
- * @return {@code this - val}
- */
- UnsignedWord subtract(int val);
-
- /**
- * Returns a Unsigned whose value is {@code (this * val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to be multiplied by this Unsigned.
- * @return {@code this * val}
- */
- UnsignedWord multiply(int val);
-
- /**
- * Returns a Unsigned whose value is {@code (this / val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value by which this Unsigned is to be divided.
- * @return {@code this / val}
- */
- UnsignedWord unsignedDivide(int val);
-
- /**
- * Returns a Unsigned whose value is {@code (this % val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value by which this Unsigned is to be divided, and the remainder computed.
- * @return {@code this % val}
- */
- UnsignedWord unsignedRemainder(int val);
-
- /**
- * Returns a Unsigned whose value is {@code (this << n)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param n shift distance, in bits.
- * @return {@code this << n}
- */
- UnsignedWord shiftLeft(int n);
-
- /**
- * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param n shift distance, in bits.
- * @return {@code this >> n}
- */
- UnsignedWord unsignedShiftRight(int n);
-
- /**
- * Returns a Unsigned whose value is {@code (this & val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to be AND'ed with this Unsigned.
- * @return {@code this & val}
- */
- UnsignedWord and(int val);
-
- /**
- * Returns a Unsigned whose value is {@code (this | val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to be OR'ed with this Unsigned.
- * @return {@code this | val}
- */
- UnsignedWord or(int val);
-
- /**
- * Returns a Unsigned whose value is {@code (this ^ val)}.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to be XOR'ed with this Unsigned.
- * @return {@code this ^ val}
- */
- UnsignedWord xor(int val);
-
- /**
- * Compares this Unsigned with the specified value.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this == val}
- */
- boolean equal(int val);
-
- /**
- * Compares this Unsigned with the specified value.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this != val}
- */
- boolean notEqual(int val);
-
- /**
- * Compares this Unsigned with the specified value.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this < val}
- */
- boolean belowThan(int val);
-
- /**
- * Compares this Unsigned with the specified value.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this <= val}
- */
- boolean belowOrEqual(int val);
-
- /**
- * Compares this Unsigned with the specified value.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this > val}
- */
- boolean aboveThan(int val);
-
- /**
- * Compares this Unsigned with the specified value.
- * <p>
- * Note that the right operand is a signed value, while the operation is performed unsigned.
- * Therefore, the result is only well-defined for positive right operands.
- *
- * @param val value to which this Unsigned is to be compared.
- * @return {@code this >= val}
- */
- boolean aboveOrEqual(int val);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordBase.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-public interface WordBase {
-
- long rawValue();
-
- /**
- * This is deprecated because of the easy to mistype name collision between {@link #equals} and
- * the other word based equality routines. In general you should never be statically calling
- * this method anyway.
- */
- @Override
- @Deprecated
- boolean equals(Object o);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.word;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-public abstract class WordFactory {
-
- /**
- * Links a method to a canonical operation represented by an {@link FactoryOpcode} val.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- protected @interface FactoryOperation {
- FactoryOpcode opcode();
- }
-
- /**
- * The canonical {@link FactoryOperation} represented by a method in a word type.
- */
- protected enum FactoryOpcode {
- ZERO,
- FROM_UNSIGNED,
- FROM_SIGNED,
- }
-
- protected interface BoxFactory {
- <T extends WordBase> T box(long val);
- }
-
- protected static BoxFactory boxFactory;
-
- /**
- * We allow subclassing, because only subclasses can access the protected inner classes that we
- * use to mark the operations.
- */
- protected WordFactory() {
- }
-
- /**
- * The constant 0, i.e., the word with no bits set. There is no difference between a signed and
- * unsigned zero.
- *
- * @return the constant 0.
- */
- @FactoryOperation(opcode = FactoryOpcode.ZERO)
- public static <T extends WordBase> T zero() {
- return boxFactory.box(0L);
- }
-
- /**
- * The null pointer, i.e., the pointer with no bits set. There is no difference to a signed or
- * unsigned {@link #zero}.
- *
- * @return the null pointer.
- */
- @FactoryOperation(opcode = FactoryOpcode.ZERO)
- public static <T extends PointerBase> T nullPointer() {
- return boxFactory.box(0L);
- }
-
- /**
- * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned
- * 64-bit value (in contrast to the semantics of a Java long).
- *
- * @param val a 64 bit unsigned value
- * @return the value cast to Word
- */
- @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
- public static <T extends UnsignedWord> T unsigned(long val) {
- return boxFactory.box(val);
- }
-
- /**
- * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is
- * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
- *
- * @param val a 64 bit unsigned value
- * @return the value cast to PointerBase
- */
- @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
- public static <T extends PointerBase> T pointer(long val) {
- return boxFactory.box(val);
- }
-
- /**
- * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned
- * 32-bit value (in contrast to the semantics of a Java int).
- *
- * @param val a 32 bit unsigned value
- * @return the value cast to Word
- */
- @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
- public static <T extends UnsignedWord> T unsigned(int val) {
- return boxFactory.box(val & 0xffffffffL);
- }
-
- /**
- * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed
- * 64-bit value (unchanged semantics of a Java long).
- *
- * @param val a 64 bit signed value
- * @return the value cast to Word
- */
- @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
- public static <T extends SignedWord> T signed(long val) {
- return boxFactory.box(val);
- }
-
- /**
- * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed
- * 32-bit value (unchanged semantics of a Java int).
- *
- * @param val a 32 bit signed value
- * @return the value cast to Word
- */
- @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
- public static <T extends SignedWord> T signed(int val) {
- return boxFactory.box(val);
- }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java Thu Apr 26 17:59:02 2018 +0200
@@ -45,14 +45,12 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.Links;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
import static javax.lang.model.element.Modifier.*;
@@ -134,7 +132,7 @@
/**
* Create the summary table for this element.
* The table should be created and initialized if needed, and configured
- * so that it is ready to add content with {@link Table#addRows(Content[])}
+ * so that it is ready to add content with {@link Table#addRow(Content[])}
* and similar methods.
*
* @return the summary table
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -37,13 +37,11 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
-
/**
* Writes annotation type field documentation in HTML format.
*
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -41,10 +41,8 @@
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
/**
* Generate the Class Information Page.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -45,14 +45,11 @@
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
import jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet;
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
/**
* Generate the Class Information Page.
@@ -122,7 +119,7 @@
Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
moduleNameDiv.addContent(Contents.SPACE);
moduleNameDiv.addContent(getModuleLink(mdle,
- new StringContent(mdle.getQualifiedName().toString())));
+ new StringContent(mdle.getQualifiedName())));
div.addContent(moduleNameDiv);
}
PackageElement pkg = utils.containingPackage(typeElement);
@@ -373,8 +370,8 @@
@Override
public void addSubClassInfo(Content classInfoTree) {
if (utils.isClass(typeElement)) {
- if (typeElement.getQualifiedName().toString().equals("java.lang.Object") ||
- typeElement.getQualifiedName().toString().equals("org.omg.CORBA.Object")) {
+ if (typeElement.getQualifiedName().contentEquals("java.lang.Object") ||
+ typeElement.getQualifiedName().contentEquals("org.omg.CORBA.Object")) {
return; // Don't generate the list, too huge
}
Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false);
@@ -415,8 +412,8 @@
if (!utils.isInterface(typeElement)) {
return;
}
- if (typeElement.getQualifiedName().toString().equals("java.lang.Cloneable") ||
- typeElement.getQualifiedName().toString().equals("java.io.Serializable")) {
+ if (typeElement.getQualifiedName().contentEquals("java.lang.Cloneable") ||
+ typeElement.getQualifiedName().contentEquals("java.io.Serializable")) {
return; // Don't generate the list, too big
}
Set<TypeElement> implcl = classtree.implementingClasses(typeElement);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,12 +38,13 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
@@ -72,10 +73,9 @@
public ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) {
super(writer, typeElement);
- VisibleMemberMap visibleMemberMap = configuration.getVisibleMemberMap(
- typeElement,
- VisibleMemberMap.Kind.CONSTRUCTORS);
- List<Element> constructors = visibleMemberMap.getMembers(typeElement);
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+ List<? extends Element> constructors = vmt.getVisibleMembers(CONSTRUCTORS);
+
for (Element constructor : constructors) {
if (utils.isProtected(constructor) || utils.isPrivate(constructor)) {
setFoundNonPubConstructor(true);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -25,6 +25,8 @@
package jdk.javadoc.internal.doclets.formats.html;
+import java.util.EnumMap;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -36,6 +38,8 @@
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
/**
* Constants and factory methods for common fragments of content
@@ -165,6 +169,8 @@
public final Content useLabel;
public final Content valueLabel;
+ private final EnumMap<VisibleMemberTable.Kind, Content> navLinkLabels;
+
private final Resources resources;
/**
@@ -289,6 +295,13 @@
typeLabel = getContent("doclet.Type");
useLabel = getContent("doclet.navClassUse");
valueLabel = getContent("doclet.Value");
+
+ navLinkLabels = new EnumMap<>(VisibleMemberTable.Kind.class);
+ navLinkLabels.put(VisibleMemberTable.Kind.INNER_CLASSES, getContent("doclet.navNested"));
+ navLinkLabels.put(VisibleMemberTable.Kind.ENUM_CONSTANTS, getContent("doclet.navEnum"));
+ navLinkLabels.put(VisibleMemberTable.Kind.FIELDS, getContent("doclet.navField"));
+ navLinkLabels.put(VisibleMemberTable.Kind.CONSTRUCTORS, getContent("doclet.navConstructor"));
+ navLinkLabels.put(VisibleMemberTable.Kind.METHODS, getContent("doclet.navMethod"));
}
/**
@@ -393,4 +406,13 @@
c.addContent(text.substring(start));
return c; // TODO: should be made immutable
}
+
+ /**
+ * Returns a content for a visible member kind.
+ * @param kind the visible member table kind.
+ * @return the string content
+ */
+ public Content getNavLinkLabelContent(VisibleMemberTable.Kind kind) {
+ return Objects.requireNonNull(navLinkLabels.get(kind));
+ }
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -107,7 +107,6 @@
* For new format.
*
* @throws DocletException if there is a problem while writing the other files
- * @see jdk.doclet.DocletEnvironment
*/
@Override // defined by AbstractDoclet
protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree)
@@ -242,7 +241,7 @@
List<TypeElement> list = new ArrayList<>(arr);
ListIterator<TypeElement> iterator = list.listIterator();
for (TypeElement klass : list) {
- if (utils.isHidden(klass) ||
+ if (utils.hasHiddenTag(klass) ||
!(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) {
continue;
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Thu Apr 26 17:59:02 2018 +0200
@@ -69,13 +69,11 @@
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.Links;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
import jdk.javadoc.internal.doclets.formats.html.markup.Script;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
@@ -94,9 +92,8 @@
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
import static com.sun.source.doctree.DocTree.Kind.*;
import static jdk.javadoc.internal.doclets.toolkit.util.CommentHelper.SPACER;
@@ -302,11 +299,12 @@
TypeElement enclosing = utils.getEnclosingTypeElement(method);
List<? extends TypeMirror> intfacs = enclosing.getInterfaces();
ExecutableElement overriddenMethod = utils.overriddenMethod(method);
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(enclosing);
// Check whether there is any implementation or overridden info to be
// printed. If no overridden or implementation info needs to be
// printed, do not print this section.
if ((!intfacs.isEmpty()
- && new ImplementedMethods(method, this.configuration).build().isEmpty() == false)
+ && vmt.getImplementedMethods(method).isEmpty() == false)
|| overriddenMethod != null) {
MethodWriterImpl.addImplementsInfo(this, method, dl);
if (overriddenMethod != null) {
@@ -1078,10 +1076,11 @@
// Find the enclosing type where the method is actually visible
// in the inheritance hierarchy.
+ ExecutableElement overriddenMethod = null;
if (refMem.getKind() == ElementKind.METHOD) {
- VisibleMemberMap vmm = configuration.getVisibleMemberMap(containing,
- VisibleMemberMap.Kind.METHODS);
- ExecutableElement overriddenMethod = vmm.getVisibleMethod((ExecutableElement)refMem);
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(containing);
+ overriddenMethod = vmt.getOverriddenMethod((ExecutableElement)refMem);
+
if (overriddenMethod != null)
containing = utils.getEnclosingTypeElement(overriddenMethod);
}
@@ -1112,6 +1111,10 @@
if (refMemName.indexOf('(') < 0) {
refMemName += utils.makeSignature((ExecutableElement)refMem, true);
}
+ if (overriddenMethod != null) {
+ // The method to actually link.
+ refMem = overriddenMethod;
+ }
}
text = plainOrCode(kind == LINK_PLAIN, new StringContent(refMemName));
@@ -1596,7 +1599,7 @@
* {@literal <a href="./com/sun/javadoc/package-summary.html">The package Page</a>}
*
* @param element the Element object whose documentation is being written.
- * @param text the text being written.
+ * @param tt the text being written.
*
* @return the text, with all the relative links redirected to work.
*/
@@ -1671,7 +1674,7 @@
* Add the annotation types of the executable receiver.
*
* @param method the executable to write the receiver annotations for.
- * @param descList list of annotation description.
+ * @param descList a list of annotation mirrors.
* @param htmltree the documentation tree to which the annotation info will be
* added
*/
@@ -1718,7 +1721,7 @@
* Adds the annotatation types for the given Element.
*
* @param element the element to write annotations for.
- * @param descList the array of {@link AnnotationDesc}.
+ * @param descList a list of annotation mirrors.
* @param htmltree the documentation tree to which the annotation info will be
* added
*/
@@ -1732,7 +1735,7 @@
*
* @param indent the number of extra spaces to indent the annotations.
* @param element the element to write annotations for.
- * @param descList the array of {@link AnnotationDesc}.
+ * @param descList a list of annotation mirrors.
* @param htmltree the documentation tree to which the annotation info will be
* added
*/
@@ -1758,9 +1761,9 @@
* the given doc.
*
* @param indent the number of extra spaces to indent the annotations.
- * @param descList the array of {@link AnnotationDesc}.
+ * @param descList a list of annotation mirrors.
* @param linkBreak if true, add new line between each member value.
- * @return an array of strings representing the annotations being
+ * @return a list of strings representing the annotations being
* documented.
*/
private List<Content> getAnnotations(int indent, List<? extends AnnotationMirror> descList, boolean linkBreak) {
@@ -1781,10 +1784,10 @@
* annotations should be returned without any filtering.
*
* @param indent the number of extra spaces to indent the annotations.
- * @param descList the array of {@link AnnotationDesc}.
+ * @param descList a list of annotation mirrors.
* @param linkBreak if true, add new line between each member value.
* @param isJava5DeclarationLocation
- * @return an array of strings representing the annotations being
+ * @return a list of strings representing the annotations being
* documented.
*/
public List<Content> getAnnotations(int indent, List<? extends AnnotationMirror> descList,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -40,13 +40,12 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
import jdk.javadoc.internal.doclets.toolkit.MethodWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
/**
* Writes method documentation in HTML format.
@@ -383,13 +382,13 @@
return;
}
Contents contents = writer.contents;
- ImplementedMethods implementedMethodsFinder =
- new ImplementedMethods(method, writer.configuration);
+ VisibleMemberTable vmt = writer.configuration
+ .getVisibleMemberTable(utils.getEnclosingTypeElement(method));
SortedSet<ExecutableElement> implementedMethods =
new TreeSet<>(utils.makeOverrideUseComparator());
- implementedMethods.addAll(implementedMethodsFinder.build());
+ implementedMethods.addAll(vmt.getImplementedMethods(method));
for (ExecutableElement implementedMeth : implementedMethods) {
- TypeMirror intfac = implementedMethodsFinder.getMethodHolder(implementedMeth);
+ TypeMirror intfac = vmt.getImplementedMethodHolder(method, implementedMeth);
intfac = utils.getDeclaredType(utils.getEnclosingTypeElement(method), intfac);
Content intfaclink = writer.getLink(new LinkInfoImpl(
writer.configuration, LinkInfoImpl.Kind.METHOD_SPECIFIED_BY, intfac));
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -30,7 +30,6 @@
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
@@ -45,7 +44,7 @@
import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter;
import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
/**
* The factory that returns HTML writers.
@@ -184,7 +183,7 @@
*/
@Override
public MemberSummaryWriter getMemberSummaryWriter(ClassWriter classWriter,
- VisibleMemberMap.Kind memberType) {
+ VisibleMemberTable.Kind memberType) {
switch (memberType) {
case CONSTRUCTORS:
return getConstructorWriter(classWriter);
@@ -209,7 +208,7 @@
*/
@Override
public MemberSummaryWriter getMemberSummaryWriter(AnnotationTypeWriter annotationTypeWriter,
- VisibleMemberMap.Kind memberType) {
+ VisibleMemberTable.Kind memberType) {
switch (memberType) {
case ANNOTATION_TYPE_FIELDS:
return (AnnotationTypeFieldWriterImpl)
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java Thu Apr 26 17:59:02 2018 +0200
@@ -30,6 +30,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.SortedSet;
import javax.lang.model.element.Element;
@@ -48,7 +49,9 @@
import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Factory for navigation bar.
@@ -414,28 +417,28 @@
case CLASS:
if (element.getKind() == ElementKind.ANNOTATION_TYPE) {
addAnnotationTypeSummaryLink("doclet.navField",
- VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, listContents);
+ ANNOTATION_TYPE_FIELDS, listContents);
addAnnotationTypeSummaryLink("doclet.navAnnotationTypeRequiredMember",
- VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, listContents);
+ ANNOTATION_TYPE_MEMBER_REQUIRED, listContents);
addAnnotationTypeSummaryLink("doclet.navAnnotationTypeOptionalMember",
- VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents);
+ ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents);
} else {
TypeElement typeElement = (TypeElement) element;
- for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) {
- if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+ for (VisibleMemberTable.Kind kind : summarySet) {
+ if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
continue;
}
- if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+ if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
continue;
}
AbstractMemberWriter writer
= ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind));
if (writer == null) {
- addContentToList(listContents,
- contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+ addContentToList(listContents, contents.getNavLinkLabelContent(kind));
} else {
addTypeSummaryLink(memberSummaryBuilder.members(kind),
- memberSummaryBuilder.getVisibleMemberMap(kind), listContents);
+ memberSummaryBuilder.getVisibleMemberTable(),
+ kind, listContents);
}
}
}
@@ -487,24 +490,25 @@
* Add the navigation summary link.
*
* @param members members to be linked
- * @param visibleMemberMap the visible inherited members map
+ * @param vmt the visible member table
+ * @param kind the visible member kind
* @param listContents the list of contents
*/
private void addTypeSummaryLink(SortedSet<? extends Element> members,
- VisibleMemberMap visibleMemberMap, List<Content> listContents) {
+ VisibleMemberTable vmt,
+ VisibleMemberTable.Kind kind, List<Content> listContents) {
if (!members.isEmpty()) {
- addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+ addTypeSummaryLink(null, kind, true, listContents);
return;
}
-
- SortedSet<TypeElement> visibleClasses = visibleMemberMap.getVisibleClasses();
+ Set<TypeElement> visibleClasses = vmt.getVisibleTypeElements();
for (TypeElement t : visibleClasses) {
- if (!configuration.getVisibleMemberMap(t, visibleMemberMap.kind).getLeafMembers().isEmpty()) {
- addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+ if (configuration.getVisibleMemberTable(t).hasVisibleMembers(kind)) {
+ addTypeSummaryLink(null, kind, true, listContents);
return;
}
}
- addTypeSummaryLink(null, visibleMemberMap.kind, false, listContents);
+ addTypeSummaryLink(null, kind, false, listContents);
}
/**
@@ -515,7 +519,7 @@
* @param link true if the members are listed and need to be linked
* @param listContents the list of contents to which the summary will be added
*/
- private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberMap.Kind kind, boolean link,
+ private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberTable.Kind kind, boolean link,
List<Content> listContents) {
switch (kind) {
case CONSTRUCTORS:
@@ -601,17 +605,17 @@
* Add the navigation Type summary link.
*
* @param label the label to be added
- * @param type the kind of member being documented
+ * @param kind the kind of member being documented
* @param listContents the list of contents to which the summary will be added
*/
- private void addAnnotationTypeSummaryLink(String label, VisibleMemberMap.Kind type, List<Content> listContents) {
+ private void addAnnotationTypeSummaryLink(String label, VisibleMemberTable.Kind kind, List<Content> listContents) {
AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder.
- getMemberSummaryWriter(type));
+ getMemberSummaryWriter(kind));
if (writer == null) {
addContentToList(listContents, contents.getContent(label));
} else {
- boolean link = !memberSummaryBuilder.getVisibleMemberMap(type).noVisibleMembers();
- switch (type) {
+ boolean link = memberSummaryBuilder.getVisibleMemberTable().hasVisibleMembers(kind);
+ switch (kind) {
case ANNOTATION_TYPE_FIELDS:
if (link) {
addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_FIELD_SUMMARY,
@@ -657,20 +661,20 @@
addAnnotationTypeDetailLink(listContents);
} else {
TypeElement typeElement = (TypeElement) element;
- for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) {
+ for (VisibleMemberTable.Kind kind : detailSet) {
AbstractMemberWriter writer
= ((AbstractMemberWriter) memberSummaryBuilder.
getMemberSummaryWriter(kind));
- if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+ if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
continue;
}
- if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+ if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
continue;
}
if (writer == null) {
- addContentToList(listContents, contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+ addContentToList(listContents, contents.getNavLinkLabelContent(kind));
} else {
- addTypeDetailLink(kind, !memberSummaryBuilder.members(kind).isEmpty(), listContents);
+ addTypeDetailLink(kind, memberSummaryBuilder.hasMembers(kind), listContents);
}
}
}
@@ -693,7 +697,7 @@
* @param link true if the members are listed and need to be linked
* @param listContents the list of contents to which the detail will be added.
*/
- protected void addTypeDetailLink(VisibleMemberMap.Kind kind, boolean link, List<Content> listContents) {
+ protected void addTypeDetailLink(VisibleMemberTable.Kind kind, boolean link, List<Content> listContents) {
switch (kind) {
case CONSTRUCTORS:
if (link) {
@@ -744,25 +748,25 @@
TypeElement annotationType = (TypeElement) element;
AbstractMemberWriter writerField
= ((AbstractMemberWriter) memberSummaryBuilder.
- getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS));
+ getMemberSummaryWriter(ANNOTATION_TYPE_FIELDS));
AbstractMemberWriter writerOptional
= ((AbstractMemberWriter) memberSummaryBuilder.
- getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL));
+ getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_OPTIONAL));
AbstractMemberWriter writerRequired
= ((AbstractMemberWriter) memberSummaryBuilder.
- getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED));
+ getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_REQUIRED));
if (writerField != null) {
- addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS,
+ addAnnotationTypeDetailLink(ANNOTATION_TYPE_FIELDS,
!configuration.utils.getAnnotationFields(annotationType).isEmpty(),
listContents);
} else {
addContentToList(listContents, contents.navField);
}
if (writerOptional != null) {
- addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL,
+ addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_OPTIONAL,
!annotationType.getAnnotationMirrors().isEmpty(), listContents);
} else if (writerRequired != null) {
- addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED,
+ addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_REQUIRED,
!annotationType.getAnnotationMirrors().isEmpty(), listContents);
} else {
addContentToList(listContents, contents.navAnnotationTypeMember);
@@ -776,7 +780,7 @@
* @param link true if the member details need to be linked
* @param listContents the list of contents to which the annotation detail will be added.
*/
- protected void addAnnotationTypeDetailLink(VisibleMemberMap.Kind type, boolean link, List<Content> listContents) {
+ protected void addAnnotationTypeDetailLink(VisibleMemberTable.Kind type, boolean link, List<Content> listContents) {
switch (type) {
case ANNOTATION_TYPE_FIELDS:
if (link) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -81,7 +81,7 @@
/**
* Verify that the only doclet that is using this toolkit is
- * {@value #TOOLKIT_DOCLET_NAME}.
+ * #TOOLKIT_DOCLET_NAME.
*/
private boolean isValidDoclet() {
if (!getClass().getName().equals(TOOLKIT_DOCLET_NAME)) {
@@ -102,10 +102,7 @@
public boolean run(DocletEnvironment docEnv) {
configuration = getConfiguration();
configuration.initConfiguration(docEnv);
- configuration.cmtUtils = new CommentUtils(configuration);
- configuration.utils = new Utils(configuration);
utils = configuration.utils;
- configuration.workArounds = new WorkArounds(configuration);
messages = configuration.getMessages();
if (!isValidDoclet()) {
@@ -189,7 +186,6 @@
* TreeWriter generation first to ensure the Class Hierarchy is built
* first and then can be used in the later generation.
*
- * @see jdk.doclet.DocletEnvironment
* @throws DocletException if there is a problem while generating the documentation
*/
private void startGeneration(DocletEnvironment docEnv) throws DocletException {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,6 @@
package jdk.javadoc.internal.doclets.toolkit;
import java.io.*;
-import java.lang.ref.*;
import java.util.*;
import javax.lang.model.element.Element;
@@ -56,9 +55,8 @@
import jdk.javadoc.internal.doclets.toolkit.util.TypeElementCatalog;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import jdk.javadoc.internal.doclets.toolkit.util.Utils.Pair;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.GetterSetter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberCache;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
import static javax.tools.Diagnostic.Kind.*;
@@ -299,8 +297,6 @@
private List<Pair<String, String>> groupPairs;
- private final Map<TypeElement, EnumMap<Kind, Reference<VisibleMemberMap>>> typeElementMemberCache;
-
public abstract Messages getMessages();
public abstract Resources getResources();
@@ -331,11 +327,6 @@
public OverviewElement overviewElement;
- // The following three fields provide caches for use by all instances of VisibleMemberMap.
- public final Map<TypeElement, List<Element>> propertiesCache = new HashMap<>();
- public final Map<Element, Element> classPropertiesMap = new HashMap<>();
- public final Map<Element, GetterSetter> getterSetterMap = new HashMap<>();
-
public DocFileFactory docFileFactory;
/**
@@ -352,6 +343,17 @@
"jdk.javadoc.internal.doclets.toolkit.resources.doclets";
/**
+ * Primarily used to disable strict checks in the regression
+ * tests allowing those tests to be executed successfully, for
+ * instance, with OpenJDK builds which may not contain FX libraries.
+ */
+ public boolean disableJavaFxStrictChecks = false;
+
+ VisibleMemberCache visibleMemberCache = null;
+
+ public PropertyUtils propertyUtils = null;
+
+ /**
* Constructs the configurations needed by the doclet.
*
* @param doclet the doclet that created this configuration
@@ -363,7 +365,6 @@
setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
metakeywords = new MetaKeywords(this);
groupPairs = new ArrayList<>(0);
- typeElementMemberCache = new HashMap<>();
}
private boolean initialized = false;
@@ -374,6 +375,15 @@
}
initialized = true;
this.docEnv = docEnv;
+ // Utils needs docEnv, safe to init now.
+ utils = new Utils(this);
+
+ // Once docEnv and Utils have been initialized, others should be safe.
+ cmtUtils = new CommentUtils(this);
+ workArounds = new WorkArounds(this);
+ visibleMemberCache = new VisibleMemberCache(this);
+ propertyUtils = new PropertyUtils(this);
+
Splitter specifiedSplitter = new Splitter(docEnv, false);
specifiedModuleElements = Collections.unmodifiableSet(specifiedSplitter.mset);
specifiedPackageElements = Collections.unmodifiableSet(specifiedSplitter.pset);
@@ -699,6 +709,13 @@
allowScriptInComments = true;
return true;
}
+ },
+ new Hidden(resources, "--disable-javafx-strict-checks") {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ disableJavaFxStrictChecks = true;
+ return true;
+ }
}
};
Set<Doclet.Option> set = new TreeSet<>();
@@ -1285,17 +1302,7 @@
return allowScriptInComments;
}
- public VisibleMemberMap getVisibleMemberMap(TypeElement te, VisibleMemberMap.Kind kind) {
- EnumMap<Kind, Reference<VisibleMemberMap>> cacheMap = typeElementMemberCache
- .computeIfAbsent(te, k -> new EnumMap<>(VisibleMemberMap.Kind.class));
-
- Reference<VisibleMemberMap> vmapRef = cacheMap.get(kind);
- // recompute, if referent has been garbage collected
- VisibleMemberMap vMap = vmapRef == null ? null : vmapRef.get();
- if (vMap == null) {
- vMap = new VisibleMemberMap(te, kind, this);
- cacheMap.put(kind, new SoftReference<>(vMap));
- }
- return vMap;
+ public synchronized VisibleMemberTable getVisibleMemberTable(TypeElement te) {
+ return visibleMemberCache.getVisibleMemberTable(te);
}
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
import javax.lang.model.element.TypeElement;
import com.sun.source.doctree.DocTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
/**
* The interface for writing member summary output.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyUtils.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.toolkit;
+
+import java.util.regex.Pattern;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+
+/**
+ * This class provides basic JavaFX property related utility methods.
+ * Refer to the JavaFX conventions in the VisibleMemberTable comments.
+ */
+public class PropertyUtils {
+
+ final TypeMirror jbObservableType;
+
+ final Pattern fxMethodPatterns;
+
+ final boolean javafx;
+
+ final Types typeUtils;
+
+ PropertyUtils(BaseConfiguration configuration) {
+
+ javafx = configuration.javafx;
+
+ typeUtils = configuration.docEnv.getTypeUtils();
+
+ // Disable strict check for JDK's without FX.
+ TypeMirror jboType = configuration.disableJavaFxStrictChecks
+ ? null
+ : configuration.utils.getSymbol("javafx.beans.Observable");
+
+ jbObservableType = jboType != null
+ ? configuration.docEnv.getTypeUtils().erasure(jboType)
+ : null;
+
+ fxMethodPatterns = javafx
+ ? Pattern.compile("[sg]et\\p{Upper}.*||is\\p{Upper}.*")
+ : null;
+ }
+
+ /**
+ * Returns a base name for a property method. Supposing we
+ * have {@code BooleanProperty acmeProperty()}, then "acme"
+ * will be returned.
+ * @param propertyMethod
+ * @return the base name of a property method.
+ */
+ public String getBaseName(ExecutableElement propertyMethod) {
+ String name = propertyMethod.getSimpleName().toString();
+ String baseName = name.substring(0, name.indexOf("Property"));
+ return baseName;
+ }
+
+ /**
+ * Returns a property getter's name. Supposing we have a property
+ * method {@code DoubleProperty acmeProperty()}, then "getAcme"
+ * will be returned.
+ * @param propertyMethod
+ * @return the property getter's name.
+ */
+ public String getGetName(ExecutableElement propertyMethod) {
+ String baseName = getBaseName(propertyMethod);
+ String fnUppercased = "" +
+ Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+ return "get" + fnUppercased;
+ }
+
+ /**
+ * Returns an "is" method's name for a property method. Supposing
+ * we have a property method {@code BooleanProperty acmeProperty()},
+ * then "isAcme" will be returned.
+ * @param propertyMethod
+ * @return the property is getter's name.
+ */
+ public String getIsName(ExecutableElement propertyMethod) {
+ String baseName = getBaseName(propertyMethod);
+ String fnUppercased = "" +
+ Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+ return "is" + fnUppercased;
+ }
+
+ /**
+ * Returns true if a property method could have an "is" method, meaning
+ * {@code isAcme} could exist for a property method.
+ * @param propertyMethod
+ * @return true if the property could have an "is" method, false otherwise.
+ */
+ public boolean hasIsMethod(ExecutableElement propertyMethod) {
+ String propertyTypeName = propertyMethod.getReturnType().toString();
+ return "boolean".equals(propertyTypeName) ||
+ propertyTypeName.endsWith("BooleanProperty");
+ }
+
+ /**
+ * Returns a property setter's name. Supposing we have a property
+ * method {@code DoubleProperty acmeProperty()}, then "setAcme"
+ * will be returned.
+ * @param propertyMethod
+ * @return the property setter's method name.
+ */
+ public String getSetName(ExecutableElement propertyMethod) {
+ String baseName = getBaseName(propertyMethod);
+ String fnUppercased = "" +
+ Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+ return "set" + fnUppercased;
+ }
+
+ /**
+ * Returns true if the given setter method is a valid property setter
+ * method.
+ * @param setterMethod
+ * @return true if setter method, false otherwise.
+ */
+ public boolean isValidSetterMethod(ExecutableElement setterMethod) {
+ return setterMethod.getReturnType().getKind() == TypeKind.VOID;
+ }
+
+ /**
+ * Returns true if the method is a property method.
+ * @param propertyMethod
+ * @return true if the method is a property method, false otherwise.
+ */
+ public boolean isPropertyMethod(ExecutableElement propertyMethod) {
+ if (!javafx ||
+ !propertyMethod.getParameters().isEmpty() ||
+ !propertyMethod.getTypeParameters().isEmpty()) {
+ return false;
+ }
+ String methodName = propertyMethod.getSimpleName().toString();
+ if (!methodName.endsWith("Property") ||
+ fxMethodPatterns.matcher(methodName).matches()) {
+ return false;
+ }
+
+ TypeMirror returnType = propertyMethod.getReturnType();
+ if (jbObservableType == null) {
+ // JavaFX references missing, make a lazy backward compatible check.
+ return returnType.getKind() != TypeKind.VOID;
+ } else {
+ // Apply strict checks since JavaFX references are available
+ returnType = typeUtils.erasure(propertyMethod.getReturnType());
+ return typeUtils.isAssignable(returnType, jbObservableType);
+ }
+ }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -29,10 +29,9 @@
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
/**
* The interface for a factory creates writers.
@@ -180,30 +179,30 @@
* Return the specified member summary writer for a given class.
*
* @param classWriter the writer for the class being documented.
- * @param memberType the {@link VisibleMemberMap} member type indicating
+ * @param memberType the {@link VisibleMemberTable} member type indicating
* the type of member summary that should be returned.
* @return the summary writer for the give class. Return null if this
* writer is not supported by the doclet.
*
- * @see VisibleMemberMap
+ * @see VisibleMemberTable
*/
public abstract MemberSummaryWriter getMemberSummaryWriter(
- ClassWriter classWriter, VisibleMemberMap.Kind memberType);
+ ClassWriter classWriter, VisibleMemberTable.Kind memberType);
/**
* Return the specified member summary writer for a given annotation type.
*
* @param annotationTypeWriter the writer for the annotation type being
* documented.
- * @param memberType the {@link VisibleMemberMap} member type indicating
+ * @param memberType the {@link VisibleMemberTable} member type indicating
* the type of member summary that should be returned.
* @return the summary writer for the give class. Return null if this
* writer is not supported by the doclet.
*
- * @see VisibleMemberMap
+ * @see VisibleMemberTable
*/
public abstract MemberSummaryWriter getMemberSummaryWriter(
- AnnotationTypeWriter annotationTypeWriter, VisibleMemberMap.Kind memberType);
+ AnnotationTypeWriter annotationTypeWriter, VisibleMemberTable.Kind memberType);
/**
* Return the writer for the serialized form.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,8 +25,14 @@
package jdk.javadoc.internal.doclets.toolkit.builders;
+import java.util.List;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind;
/**
* The superclass for all member builders. Member builders are only executed
@@ -42,13 +48,19 @@
*/
public abstract class AbstractMemberBuilder extends AbstractBuilder {
+ final protected TypeElement typeElement;
+
+ final protected VisibleMemberTable visibleMemberTable;
+
/**
* Construct a SubBuilder.
* @param context a context object, providing information used in this run
* of the doclet.
*/
- public AbstractMemberBuilder(Context context) {
+ public AbstractMemberBuilder(Context context, TypeElement typeElement) {
super(context);
+ this.typeElement = typeElement;
+ visibleMemberTable = configuration.getVisibleMemberTable(typeElement);
}
/**
@@ -77,4 +89,14 @@
* @return true if this subbuilder has anything to document
*/
public abstract boolean hasMembersToDocument();
+
+ /**
+ * Returns a list of visible elements of the specified kind in this
+ * type element.
+ * @param kind of members
+ * @return a list of members
+ */
+ protected List<? extends Element> getVisibleMembers(Kind kind) {
+ return visibleMemberTable.getVisibleMembers(kind);
+ }
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -34,7 +34,7 @@
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
/**
@@ -50,16 +50,6 @@
public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder {
/**
- * The annotation type whose members are being documented.
- */
- protected TypeElement typeElement;
-
- /**
- * The visible members for the given class.
- */
- protected VisibleMemberMap visibleMemberMap;
-
- /**
* The writer to output the member documentation.
*/
protected AnnotationTypeFieldWriter writer;
@@ -67,7 +57,7 @@
/**
* The list of members being documented.
*/
- protected List<Element> members;
+ protected List<? extends Element> members;
/**
* The index of the current member that is being documented at this point
@@ -86,12 +76,10 @@
protected AnnotationTypeFieldBuilder(Context context,
TypeElement typeElement,
AnnotationTypeFieldWriter writer,
- VisibleMemberMap.Kind memberType) {
- super(context);
- this.typeElement = typeElement;
+ VisibleMemberTable.Kind memberType) {
+ super(context, typeElement);
this.writer = writer;
- this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
- this.members = this.visibleMemberMap.getMembers(typeElement);
+ this.members = getVisibleMembers(memberType);
}
@@ -107,7 +95,7 @@
Context context, TypeElement typeElement,
AnnotationTypeFieldWriter writer) {
return new AnnotationTypeFieldBuilder(context, typeElement,
- writer, VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
+ writer, VisibleMemberTable.Kind.ANNOTATION_TYPE_FIELDS);
}
/**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,8 +31,8 @@
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for optional annotation type members.
@@ -57,8 +57,7 @@
private AnnotationTypeOptionalMemberBuilder(Context context,
TypeElement typeElement,
AnnotationTypeOptionalMemberWriter writer) {
- super(context, typeElement, writer,
- VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
+ super(context, typeElement, writer, ANNOTATION_TYPE_MEMBER_OPTIONAL);
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -34,8 +34,9 @@
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for required annotation type members.
@@ -50,15 +51,6 @@
*/
public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
- /**
- * The annotation type whose members are being documented.
- */
- protected TypeElement typeElement;
-
- /**
- * The visible members for the given class.
- */
- protected VisibleMemberMap visibleMemberMap;
/**
* The writer to output the member documentation.
@@ -68,7 +60,7 @@
/**
* The list of members being documented.
*/
- protected List<Element> members;
+ protected List<? extends Element> members;
/**
* The index of the current member that is being documented at this point
@@ -87,12 +79,10 @@
protected AnnotationTypeRequiredMemberBuilder(Context context,
TypeElement typeElement,
AnnotationTypeRequiredMemberWriter writer,
- VisibleMemberMap.Kind memberType) {
- super(context);
- this.typeElement = typeElement;
+ VisibleMemberTable.Kind memberType) {
+ super(context, typeElement);
this.writer = writer;
- this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
- this.members = this.visibleMemberMap.getMembers(typeElement);
+ this.members = getVisibleMembers(memberType);
}
@@ -108,8 +98,7 @@
Context context, TypeElement typeElement,
AnnotationTypeRequiredMemberWriter writer) {
return new AnnotationTypeRequiredMemberBuilder(context, typeElement,
- writer,
- VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
+ writer, ANNOTATION_TYPE_MEMBER_REQUIRED);
}
/**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -35,8 +35,9 @@
import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds the Constants Summary Page.
@@ -262,9 +263,8 @@
* @return true if the given package has constant fields to document.
*/
private boolean hasConstantField (TypeElement typeElement) {
- VisibleMemberMap visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.FIELDS);
- List<Element> fields = visibleMemberMapFields.getLeafMembers();
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+ List<? extends Element> fields = vmt.getVisibleMembers(FIELDS);
for (Element f : fields) {
VariableElement field = (VariableElement)f;
if (field.getConstantValue() != null) {
@@ -279,7 +279,7 @@
* Return true if the given package name has been printed. Also
* return true if the root of this package has been printed.
*
- * @param pkgname the name of the package to check.
+ * @param pkg the name of the package to check.
*/
private boolean hasPrintedPackageIndex(PackageElement pkg) {
for (PackageElement printedPkg : printedPackageHeaders) {
@@ -298,16 +298,6 @@
private class ConstantFieldBuilder {
/**
- * The map used to get the visible variables.
- */
- protected VisibleMemberMap visibleMemberMapFields = null;
-
- /**
- * The map used to get the visible variables.
- */
- protected VisibleMemberMap visibleMemberMapEnumConst = null;
-
- /**
* The typeElement that we are examining constants for.
*/
protected TypeElement typeElement;
@@ -318,10 +308,6 @@
*/
public ConstantFieldBuilder(TypeElement typeElement) {
this.typeElement = typeElement;
- visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.FIELDS);
- visibleMemberMapEnumConst = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.ENUM_CONSTANTS);
}
/**
@@ -342,8 +328,10 @@
* @return the set of visible constant fields for the given type.
*/
protected SortedSet<VariableElement> members() {
- List<Element> members = visibleMemberMapFields.getLeafMembers();
- members.addAll(visibleMemberMapEnumConst.getLeafMembers());
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+ List<Element> members = new ArrayList<>();
+ members.addAll(vmt.getVisibleMembers(FIELDS));
+ members.addAll(vmt.getVisibleMembers(ENUM_CONSTANTS));
SortedSet<VariableElement> includes =
new TreeSet<>(utils.makeGeneralPurposeComparator());
for (Element element : members) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -35,8 +35,8 @@
import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for a constructor.
@@ -57,16 +57,6 @@
private ExecutableElement currentConstructor;
/**
- * The class whose constructors are being documented.
- */
- private final TypeElement typeElement;
-
- /**
- * The visible constructors for the given class.
- */
- private final VisibleMemberMap visibleMemberMap;
-
- /**
* The writer to output the constructor documentation.
*/
private final ConstructorWriter writer;
@@ -74,7 +64,7 @@
/**
* The constructors being documented.
*/
- private final List<Element> constructors;
+ private final List<? extends Element> constructors;
/**
* Construct a new ConstructorBuilder.
@@ -86,12 +76,9 @@
private ConstructorBuilder(Context context,
TypeElement typeElement,
ConstructorWriter writer) {
- super(context);
- this.typeElement = typeElement;
+ super(context, typeElement);
this.writer = writer;
- visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.CONSTRUCTORS);
- constructors = visibleMemberMap.getMembers(typeElement);
+ constructors = getVisibleMembers(CONSTRUCTORS);
for (Element ctor : constructors) {
if (utils.isProtected(ctor) || utils.isPrivate(ctor)) {
writer.setFoundNonPubConstructor(true);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -35,8 +35,8 @@
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.EnumConstantWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for a enum constants.
@@ -52,16 +52,6 @@
public class EnumConstantBuilder extends AbstractMemberBuilder {
/**
- * The class whose enum constants are being documented.
- */
- private final TypeElement typeElement;
-
- /**
- * The visible enum constantss for the given class.
- */
- private final VisibleMemberMap visibleMemberMap;
-
- /**
* The writer to output the enum constants documentation.
*/
private final EnumConstantWriter writer;
@@ -69,7 +59,7 @@
/**
* The set of enum constants being documented.
*/
- private final List<Element> enumConstants;
+ private final List<? extends Element> enumConstants;
/**
* The current enum constant that is being documented at this point
@@ -86,12 +76,9 @@
*/
private EnumConstantBuilder(Context context,
TypeElement typeElement, EnumConstantWriter writer) {
- super(context);
- this.typeElement = typeElement;
+ super(context, typeElement);
this.writer = writer;
- visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.ENUM_CONSTANTS);
- enumConstants = visibleMemberMap.getMembers(typeElement);
+ enumConstants = getVisibleMembers(ENUM_CONSTANTS);
}
/**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -35,8 +35,8 @@
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.FieldWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for a field.
@@ -52,16 +52,6 @@
public class FieldBuilder extends AbstractMemberBuilder {
/**
- * The class whose fields are being documented.
- */
- private final TypeElement typeElement;
-
- /**
- * The visible fields for the given class.
- */
- private final VisibleMemberMap visibleMemberMap;
-
- /**
* The writer to output the field documentation.
*/
private final FieldWriter writer;
@@ -69,7 +59,7 @@
/**
* The list of fields being documented.
*/
- private final List<Element> fields;
+ private final List<? extends Element> fields;
/**
* The index of the current field that is being documented at this point
@@ -85,14 +75,11 @@
* @param writer the doclet specific writer.
*/
private FieldBuilder(Context context,
- TypeElement typeElement,
- FieldWriter writer) {
- super(context);
- this.typeElement = typeElement;
+ TypeElement typeElement,
+ FieldWriter writer) {
+ super(context, typeElement);
this.writer = writer;
- visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.FIELDS);
- fields = visibleMemberMap.getLeafMembers();
+ fields = getVisibleMembers(FIELDS);
}
/**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -27,12 +27,15 @@
import java.text.MessageFormat;
import java.util.*;
+import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.ElementFilter;
+import com.sun.source.doctree.DocCommentTree;
import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.DocTree.Kind;
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
@@ -42,9 +45,11 @@
import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
+
/**
* Builds the member summary.
* There are two anonymous subtype variants of this builder, created
@@ -69,12 +74,9 @@
/**
* The member summary writers for the given class.
*/
- private final EnumMap<VisibleMemberMap.Kind, MemberSummaryWriter> memberSummaryWriters;
+ private final EnumMap<VisibleMemberTable.Kind, MemberSummaryWriter> memberSummaryWriters;
- /**
- * The type being documented.
- */
- protected final TypeElement typeElement;
+ final PropertyHelper pHelper;
/**
* Construct a new MemberSummaryBuilder.
@@ -83,11 +85,10 @@
* @param typeElement the type element.
*/
private MemberSummaryBuilder(Context context, TypeElement typeElement) {
- super(context);
- this.typeElement = typeElement;
- memberSummaryWriters = new EnumMap<>(VisibleMemberMap.Kind.class);
-
- comparator = utils.makeGeneralPurposeComparator();
+ super(context, typeElement);
+ memberSummaryWriters = new EnumMap<>(VisibleMemberTable.Kind.class);
+ comparator = utils.makeIndexUseComparator();
+ pHelper = new PropertyHelper(this);
}
/**
@@ -113,20 +114,14 @@
@Override
public boolean hasMembersToDocument() {
- for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
- VisibleMemberMap members = getVisibleMemberMap(kind);
- if (!members.noVisibleMembers()) {
- return true;
- }
- }
- return false;
+ return visibleMemberTable.hasVisibleMembers();
}
};
WriterFactory wf = context.configuration.getWriterFactory();
- for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
- MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
- ? null
- : wf.getMemberSummaryWriter(classWriter, kind);
+ for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
+ MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
+ ? wf.getMemberSummaryWriter(classWriter, kind)
+ : null;
builder.memberSummaryWriters.put(kind, msw);
}
return builder;
@@ -157,10 +152,10 @@
}
};
WriterFactory wf = context.configuration.getWriterFactory();
- for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
- MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
- ? null
- : wf.getMemberSummaryWriter(annotationTypeWriter, kind);
+ for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
+ MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
+ ? wf.getMemberSummaryWriter(annotationTypeWriter, kind)
+ : null;
builder.memberSummaryWriters.put(kind, msw);
}
return builder;
@@ -169,13 +164,12 @@
/**
* Return the specified visible member map.
*
- * @param kind the kind of visible member map to return.
* @return the specified visible member map.
* @throws ArrayIndexOutOfBoundsException when the type is invalid.
- * @see VisibleMemberMap
+ * @see VisibleMemberTable
*/
- public VisibleMemberMap getVisibleMemberMap(VisibleMemberMap.Kind kind) {
- return configuration.getVisibleMemberMap(typeElement, kind);
+ public VisibleMemberTable getVisibleMemberTable() {
+ return visibleMemberTable;
}
/**.
@@ -184,9 +178,9 @@
* @param kind the kind of member summary writer to return.
* @return the specified member summary writer.
* @throws ArrayIndexOutOfBoundsException when the type is invalid.
- * @see VisibleMemberMap
+ * @see VisibleMemberTable
*/
- public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberMap.Kind kind) {
+ public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberTable.Kind kind) {
return memberSummaryWriters.get(kind);
}
@@ -197,25 +191,31 @@
*
* @param kind the kind of elements to return.
* @return a list of methods that will be documented.
- * @see VisibleMemberMap
+ * @see VisibleMemberTable
*/
- public SortedSet<Element> members(VisibleMemberMap.Kind kind) {
+ public SortedSet<Element> members(VisibleMemberTable.Kind kind) {
TreeSet<Element> out = new TreeSet<>(comparator);
- out.addAll(getVisibleMemberMap(kind).getLeafMembers());
+ out.addAll(getVisibleMembers(kind));
return out;
}
/**
+ * Returns true if there are members of the given kind, false otherwise.
+ * @param kind
+ * @return true if there are members of the given kind, false otherwise
+ */
+ public boolean hasMembers(VisibleMemberTable.Kind kind) {
+ return !getVisibleMembers(kind).isEmpty();
+ }
+
+ /**
* Build the summary for the enum constants.
*
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildEnumConstantsSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.ENUM_CONSTANTS);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.ENUM_CONSTANTS);
- addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(ENUM_CONSTANTS);
+ addSummary(writer, ENUM_CONSTANTS, false, memberSummaryTree);
}
/**
@@ -224,11 +224,8 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildAnnotationTypeFieldsSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
- addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_FIELDS);
+ addSummary(writer, ANNOTATION_TYPE_FIELDS, false, memberSummaryTree);
}
/**
@@ -237,11 +234,8 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildAnnotationTypeOptionalMemberSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
- addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_OPTIONAL);
+ addSummary(writer, ANNOTATION_TYPE_MEMBER_OPTIONAL, false, memberSummaryTree);
}
/**
@@ -250,11 +244,8 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildAnnotationTypeRequiredMemberSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
- addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_REQUIRED);
+ addSummary(writer, ANNOTATION_TYPE_MEMBER_REQUIRED, false, memberSummaryTree);
}
/**
@@ -263,11 +254,8 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildFieldsSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.FIELDS);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.FIELDS);
- addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(FIELDS);
+ addSummary(writer, FIELDS, true, memberSummaryTree);
}
/**
@@ -276,11 +264,8 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildPropertiesSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.PROPERTIES);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.PROPERTIES);
- addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(PROPERTIES);
+ addSummary(writer, PROPERTIES, true, memberSummaryTree);
}
/**
@@ -289,11 +274,8 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildNestedClassesSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.INNER_CLASSES);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.INNER_CLASSES);
- addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(INNER_CLASSES);
+ addSummary(writer, INNER_CLASSES, true, memberSummaryTree);
}
/**
@@ -302,11 +284,8 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildMethodsSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.METHODS);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.METHODS);
- addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(METHODS);
+ addSummary(writer, METHODS, true, memberSummaryTree);
}
/**
@@ -315,28 +294,25 @@
* @param memberSummaryTree the content tree to which the documentation will be added
*/
protected void buildConstructorsSummary(Content memberSummaryTree) {
- MemberSummaryWriter writer =
- memberSummaryWriters.get(VisibleMemberMap.Kind.CONSTRUCTORS);
- VisibleMemberMap visibleMemberMap =
- getVisibleMemberMap(VisibleMemberMap.Kind.CONSTRUCTORS);
- addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+ MemberSummaryWriter writer = memberSummaryWriters.get(CONSTRUCTORS);
+ addSummary(writer, CONSTRUCTORS, false, memberSummaryTree);
}
/**
* Build the member summary for the given members.
*
* @param writer the summary writer to write the output.
- * @param visibleMemberMap the given members to summarize.
+ * @param kind the kind of members to summarize.
* @param summaryTreeList list of content trees to which the documentation will be added
*/
private void buildSummary(MemberSummaryWriter writer,
- VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
- SortedSet<Element> members = asSortedSet(visibleMemberMap.getLeafMembers());
+ VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
+ SortedSet<? extends Element> members = asSortedSet(getVisibleMembers(kind));
if (!members.isEmpty()) {
for (Element member : members) {
- final Element property = visibleMemberMap.getPropertyElement(member);
+ final Element property = pHelper.getPropertyElement(member);
if (property != null) {
- processProperty(visibleMemberMap, member, property);
+ processProperty(member, property);
}
List<? extends DocTree> firstSentenceTags = utils.getFirstSentenceTrees(member);
if (utils.isExecutableElement(member) && firstSentenceTags.isEmpty()) {
@@ -367,12 +343,10 @@
* the see tags if the appropriate property getter and setter are
* available.
*
- * @param visibleMemberMap the members information.
* @param member the member which is to be augmented.
* @param property the original property documentation.
*/
- private void processProperty(VisibleMemberMap visibleMemberMap,
- Element member,
+ private void processProperty(Element member,
Element property) {
CommentUtils cmtutils = configuration.cmtUtils;
final boolean isSetter = isSetter(member);
@@ -418,8 +392,8 @@
//add @see tags
if (!isGetter && !isSetter) {
- ExecutableElement getter = (ExecutableElement) visibleMemberMap.getGetterForProperty(member);
- ExecutableElement setter = (ExecutableElement) visibleMemberMap.getSetterForProperty(member);
+ ExecutableElement getter = pHelper.getGetterForProperty((ExecutableElement)member);
+ ExecutableElement setter = pHelper.getSetterForProperty((ExecutableElement)member);
if (null != getter) {
StringBuilder sb = new StringBuilder("#");
@@ -465,47 +439,28 @@
* Build the inherited member summary for the given methods.
*
* @param writer the writer for this member summary.
- * @param visibleMemberMap the map for the members to document.
+ * @param kind the kind of members to document.
* @param summaryTreeList list of content trees to which the documentation will be added
*/
private void buildInheritedSummary(MemberSummaryWriter writer,
- VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
- for (TypeElement inheritedClass : visibleMemberMap.getVisibleClasses()) {
+ VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
+ VisibleMemberTable visibleMemberTable = getVisibleMemberTable();
+ SortedSet<? extends Element> inheritedMembersFromMap = asSortedSet(visibleMemberTable.getAllVisibleMembers(kind));
+
+ for (TypeElement inheritedClass : visibleMemberTable.getVisibleTypeElements()) {
if (!(utils.isPublic(inheritedClass) || utils.isLinkable(inheritedClass))) {
continue;
}
if (inheritedClass == typeElement) {
continue;
}
- SortedSet<Element> inheritedMembersFromMap = asSortedSet(
- visibleMemberMap.getMembers(inheritedClass));
- if (!inheritedMembersFromMap.isEmpty()) {
+ List<Element> members = inheritedMembersFromMap.stream()
+ .filter(e -> utils.getEnclosingTypeElement(e) == inheritedClass)
+ .collect(Collectors.toList());
+ if (!members.isEmpty()) {
SortedSet<Element> inheritedMembers = new TreeSet<>(comparator);
- List<ExecutableElement> enclosedSuperMethods = utils.getMethods(inheritedClass);
- for (Element inheritedMember : inheritedMembersFromMap) {
- if (visibleMemberMap.kind != VisibleMemberMap.Kind.METHODS) {
- inheritedMembers.add(inheritedMember);
- continue;
- }
-
- // Skip static methods in interfaces they are not inherited
- if (utils.isInterface(inheritedClass) && utils.isStatic(inheritedMember))
- continue;
-
- // If applicable, filter those overridden methods that
- // should not be documented in the summary/detail sections,
- // and instead document them in the footnote. Care must be taken
- // to handle JavaFX property methods, which have no source comments,
- // but comments for these are synthesized on the output.
- ExecutableElement inheritedMethod = (ExecutableElement)inheritedMember;
- if (enclosedSuperMethods.stream()
- .anyMatch(e -> utils.executableMembersEqual(inheritedMethod, e) &&
- (!utils.isSimpleOverride(e) || visibleMemberMap.getPropertyElement(e) != null))) {
- inheritedMembers.add(inheritedMember);
- }
- }
-
+ inheritedMembers.addAll(members);
Content inheritedTree = writer.getInheritedSummaryHeader(inheritedClass);
Content linksTree = writer.getInheritedSummaryLinksTree();
addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer);
@@ -529,17 +484,17 @@
* Add the summary for the documentation.
*
* @param writer the writer for this member summary.
- * @param visibleMemberMap the map for the members to document.
+ * @param kind the kind of members to document.
* @param showInheritedSummary true if inherited summary should be documented
* @param memberSummaryTree the content tree to which the documentation will be added
*/
private void addSummary(MemberSummaryWriter writer,
- VisibleMemberMap visibleMemberMap, boolean showInheritedSummary,
+ VisibleMemberTable.Kind kind, boolean showInheritedSummary,
Content memberSummaryTree) {
LinkedList<Content> summaryTreeList = new LinkedList<>();
- buildSummary(writer, visibleMemberMap, summaryTreeList);
+ buildSummary(writer, kind, summaryTreeList);
if (showInheritedSummary)
- buildInheritedSummary(writer, visibleMemberMap, summaryTreeList);
+ buildInheritedSummary(writer, kind, summaryTreeList);
if (!summaryTreeList.isEmpty()) {
Content memberTree = writer.getMemberSummaryHeader(typeElement, memberSummaryTree);
summaryTreeList.stream().forEach(memberTree::addContent);
@@ -547,9 +502,91 @@
}
}
- private SortedSet<Element> asSortedSet(Collection<Element> members) {
+ private SortedSet<? extends Element> asSortedSet(Collection<? extends Element> members) {
SortedSet<Element> out = new TreeSet<>(comparator);
out.addAll(members);
return out;
}
+
+ static class PropertyHelper {
+
+ private final Map<Element, Element> classPropertiesMap = new HashMap<>();
+
+ private final MemberSummaryBuilder builder;
+
+ PropertyHelper(MemberSummaryBuilder builder) {
+ this.builder = builder;
+ computeProperties();
+ }
+
+ private void computeProperties() {
+ VisibleMemberTable vmt = builder.getVisibleMemberTable();
+ List<ExecutableElement> props = ElementFilter.methodsIn(vmt.getVisibleMembers(PROPERTIES));
+ for (ExecutableElement propertyMethod : props) {
+ ExecutableElement getter = vmt.getPropertyGetter(propertyMethod);
+ ExecutableElement setter = vmt.getPropertySetter(propertyMethod);
+ VariableElement field = vmt.getPropertyField(propertyMethod);
+
+ addToPropertiesMap(propertyMethod, field, getter, setter);
+ }
+ }
+
+ private void addToPropertiesMap(ExecutableElement propertyMethod,
+ VariableElement field,
+ ExecutableElement getter,
+ ExecutableElement setter) {
+ if (field == null || builder.utils.getDocCommentTree(field) == null) {
+ addToPropertiesMap(propertyMethod, propertyMethod);
+ addToPropertiesMap(getter, propertyMethod);
+ addToPropertiesMap(setter, propertyMethod);
+ } else {
+ addToPropertiesMap(propertyMethod, field);
+ addToPropertiesMap(getter, field);
+ addToPropertiesMap(setter, field);
+ }
+ }
+
+ private void addToPropertiesMap(Element propertyMethod,
+ Element commentSource) {
+ if (null == propertyMethod || null == commentSource) {
+ return;
+ }
+ DocCommentTree docTree = builder.utils.getDocCommentTree(propertyMethod);
+
+ /* The second condition is required for the property buckets. In
+ * this case the comment is at the property method (not at the field)
+ * and it needs to be listed in the map.
+ */
+ if ((docTree == null) || propertyMethod.equals(commentSource)) {
+ classPropertiesMap.put(propertyMethod, commentSource);
+ }
+ }
+
+ /**
+ * Returns the property field documentation belonging to the given member.
+ * @param element the member for which the property documentation is needed.
+ * @return the property field documentation, null if there is none.
+ */
+ public Element getPropertyElement(Element element) {
+ return classPropertiesMap.get(element);
+ }
+
+ /**
+ * Returns the getter documentation belonging to the given property method.
+ * @param propertyMethod the method for which the getter is needed.
+ * @return the getter documentation, null if there is none.
+ */
+ public ExecutableElement getGetterForProperty(ExecutableElement propertyMethod) {
+ return builder.getVisibleMemberTable().getPropertyGetter(propertyMethod);
+ }
+
+ /**
+ * Returns the setter documentation belonging to the given property method.
+ * @param propertyMethod the method for which the setter is needed.
+ * @return the setter documentation, null if there is none.
+ */
+ public ExecutableElement getSetterForProperty(ExecutableElement propertyMethod) {
+ return builder.getVisibleMemberTable().getPropertySetter(propertyMethod);
+ }
+ }
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -37,8 +37,8 @@
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.MethodWriter;
import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for a method.
@@ -60,16 +60,6 @@
private ExecutableElement currentMethod;
/**
- * The class whose methods are being documented.
- */
- private final TypeElement typeElement;
-
- /**
- * The visible methods for the given class.
- */
- private final VisibleMemberMap visibleMemberMap;
-
- /**
* The writer to output the method documentation.
*/
private final MethodWriter writer;
@@ -77,7 +67,7 @@
/**
* The methods being documented.
*/
- private final List<Element> methods;
+ private final List<? extends Element> methods;
/**
@@ -90,12 +80,9 @@
private MethodBuilder(Context context,
TypeElement typeElement,
MethodWriter writer) {
- super(context);
- this.typeElement = typeElement;
+ super(context, typeElement);
this.writer = writer;
- visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.METHODS);
- methods = visibleMemberMap.getLeafMembers();
+ methods = getVisibleMembers(METHODS);
}
/**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -35,8 +35,9 @@
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.PropertyWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Builds documentation for a property.
@@ -52,16 +53,6 @@
public class PropertyBuilder extends AbstractMemberBuilder {
/**
- * The class whose properties are being documented.
- */
- private final TypeElement typeElement;
-
- /**
- * The visible properties for the given class.
- */
- private final VisibleMemberMap visibleMemberMap;
-
- /**
* The writer to output the property documentation.
*/
private final PropertyWriter writer;
@@ -69,7 +60,7 @@
/**
* The list of properties being documented.
*/
- private final List<Element> properties;
+ private final List<? extends Element> properties;
/**
* The index of the current property that is being documented at this point
@@ -87,12 +78,9 @@
private PropertyBuilder(Context context,
TypeElement typeElement,
PropertyWriter writer) {
- super(context);
- this.typeElement = typeElement;
+ super(context, typeElement);
this.writer = writer;
- visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
- VisibleMemberMap.Kind.PROPERTIES);
- properties = visibleMemberMap.getMembers(typeElement);
+ properties = getVisibleMembers(PROPERTIES);
}
/**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties Thu Apr 26 17:59:02 2018 +0200
@@ -84,7 +84,6 @@
doclet.noInheritedDoc=@inheritDoc used but {0} does not override or implement any method.
# doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
doclet.tag_misuse=Tag {0} cannot be used in {1} documentation. It can only be used in the following types of documentation: {2}.
-doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
doclet.Package_Summary=Package Summary
doclet.Requires_Summary=Requires
doclet.Indirect_Requires_Summary=Indirect Requires
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties Thu Apr 26 17:59:02 2018 +0200
@@ -75,7 +75,6 @@
doclet.noInheritedDoc=@inheritDoc\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u304C\u3001{0}\u306F\u3069\u306E\u30E1\u30BD\u30C3\u30C9\u3082\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u5B9F\u88C5\u3057\u3066\u3044\u307E\u305B\u3093\u3002
# doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
doclet.tag_misuse={0}\u30BF\u30B0\u306F{1}\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u4F7F\u7528\u3067\u304D\u308B\u306E\u306F\u6B21\u306E\u30BF\u30A4\u30D7\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u306E\u307F\u3067\u3059: {2}\u3002
-doclet.javafx_tag_misuse=\u30BF\u30B0@propertyGetter\u3001@propertySetter\u304A\u3088\u3073@propertyDescription\u306F\u3001JavaFX\u306E\u30D7\u30ED\u30D1\u30C6\u30A3getter\u3068setter\u306E\u307F\u3067\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
doclet.Package_Summary=\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u6982\u8981
doclet.Requires_Summary=\u5FC5\u8981
doclet.Indirect_Requires_Summary=\u9593\u63A5\u7684\u306B\u5FC5\u8981
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties Thu Apr 26 17:59:02 2018 +0200
@@ -75,7 +75,6 @@
doclet.noInheritedDoc=\u4F7F\u7528\u4E86 @inheritDoc, \u4F46{0}\u672A\u8986\u76D6\u6216\u5B9E\u73B0\u4EFB\u4F55\u65B9\u6CD5\u3002
# doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
doclet.tag_misuse=\u4E0D\u80FD\u5728{1}\u6587\u6863\u4E2D\u4F7F\u7528\u6807\u8BB0{0}\u3002\u53EA\u80FD\u5728\u4EE5\u4E0B\u7C7B\u578B\u7684\u6587\u6863\u4E2D\u4F7F\u7528\u8BE5\u6807\u8BB0: {2}\u3002
-doclet.javafx_tag_misuse=\u6807\u8BB0 @propertyGetter, @propertySetter \u548C @propertyDescription \u53EA\u80FD\u5728 JavaFX \u5C5E\u6027 getter \u548C setter \u4E2D\u4F7F\u7528\u3002
doclet.Package_Summary=\u7A0B\u5E8F\u5305\u6982\u8981
doclet.Requires_Summary=\u5FC5\u9700\u9879
doclet.Indirect_Requires_Summary=\u95F4\u63A5\u5FC5\u9700\u9879
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,7 +26,6 @@
package jdk.javadoc.internal.doclets.toolkit.taglets;
import java.io.*;
-import java.lang.reflect.InvocationTargetException;
import java.util.*;
import javax.lang.model.element.Element;
@@ -180,8 +179,7 @@
private final boolean showauthor;
/**
- * True if we want to use JavaFX-related tags (@propertyGetter,
- * @propertySetter, @propertyDescription, @defaultValue, @treatAsPrivate).
+ * True if we want to use JavaFX-related tags (@defaultValue, @treatAsPrivate).
*/
private final boolean javafx;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassTree.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassTree.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -161,7 +161,6 @@
* have their own sub-class lists.
*
* @param classes all the classes in this run.
- * @param configuration the current configuration of the doclet.
*/
private void buildTree(Iterable<TypeElement> classes) {
for (TypeElement aClass : classes) {
@@ -174,7 +173,7 @@
continue;
}
- if (utils.isHidden(aClass)) {
+ if (utils.hasHiddenTag(aClass)) {
continue;
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java Thu Apr 26 17:59:02 2018 +0200
@@ -47,7 +47,8 @@
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Map all class uses for a given class.
@@ -243,8 +244,9 @@
mapExecutable(ctor);
}
- VisibleMemberMap vmm = configuration.getVisibleMemberMap(aClass, Kind.METHODS);
- List<ExecutableElement> methods = ElementFilter.methodsIn(vmm.getMembers(aClass));
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(aClass);
+ List<ExecutableElement> methods = ElementFilter.methodsIn(vmt.getMembers(METHODS));
+
for (ExecutableElement method : methods) {
mapExecutable(method);
mapTypeParameters(classToMethodTypeParam, method, method);
@@ -554,8 +556,8 @@
* Map the AnnotationType to the members that use them as type parameters.
*
* @param map the map the insert the information into.
- * @param element whose type parameters are being checked.
- * @param holder the holder that owns the type parameters.
+ * @param e whose type parameters are being checked.
+ * @param holder owning the type parameters.
*/
private <T extends Element> void mapAnnotations(final Map<TypeElement, List<T>> map,
Element e, final T holder) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -276,9 +276,10 @@
//NOTE: When we fix the bug where ClassDoc.interfaceTypes() does
// not pass all implemented interfaces, we will use the
// appropriate element here.
- ImplementedMethods implMethods
- = new ImplementedMethods((ExecutableElement) input.element, configuration);
- List<ExecutableElement> implementedMethods = implMethods.build();
+ TypeElement encl = utils.getEnclosingTypeElement(input.element);
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(encl);
+ List<ExecutableElement> implementedMethods =
+ vmt.getImplementedMethods((ExecutableElement)input.element);
for (ExecutableElement implementedMethod : implementedMethods) {
inheritedSearchInput.element = implementedMethod;
output = search(configuration, inheritedSearchInput);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ImplementedMethods.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.*;
-
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-
-/**
- * For a given class method, build an array of interface methods which it
- * implements.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- */
-public class ImplementedMethods {
-
- private final Map<ExecutableElement, TypeMirror> interfaces = new HashMap<>();
- private final List<ExecutableElement> methlist = new ArrayList<>();
- private final Utils utils;
- private final TypeElement typeElement;
- private final ExecutableElement method;
-
- public ImplementedMethods(ExecutableElement method, BaseConfiguration configuration) {
- this.method = method;
- this.utils = configuration.utils;
- typeElement = utils.getEnclosingTypeElement(method);
- }
-
- /**
- * Return the array of interface methods which the method passed in the
- * constructor is implementing. The search/build order is as follows:
- * <pre>
- * 1. Search in all the immediate interfaces which this method's class is
- * implementing. Do it recursively for the superinterfaces as well.
- * 2. Traverse all the superclasses and search recursively in the
- * interfaces which those superclasses implement.
- *</pre>
- *
- * @return SortedSet<ExecutableElement> of implemented methods.
- */
- public List<ExecutableElement> build() {
- buildImplementedMethodList();
- return methlist;
- }
-
- public TypeMirror getMethodHolder(ExecutableElement ee) {
- return interfaces.get(ee);
- }
-
- /**
- * Search for the method in the array of interfaces. If found check if it is
- * overridden by any other subinterface method which this class
- * implements. If it is not overidden, add it in the method list.
- * Do this recursively for all the extended interfaces for each interface
- * from the array passed.
- */
- private void buildImplementedMethodList() {
- Set<TypeMirror> intfacs = utils.getAllInterfaces(typeElement);
- for (TypeMirror interfaceType : intfacs) {
- ExecutableElement found = utils.findMethod(utils.asTypeElement(interfaceType), method);
- if (found != null) {
- removeOverriddenMethod(found);
- if (!overridingMethodFound(found)) {
- methlist.add(found);
- interfaces.put(found, interfaceType);
- }
- }
- }
- }
-
- /**
- * Search in the method list and check if it contains a method which
- * is overridden by the method as parameter. If found, remove the
- * overridden method from the method list.
- *
- * @param method Is this method overriding a method in the method list.
- */
- private void removeOverriddenMethod(ExecutableElement method) {
- TypeElement overriddenClass = utils.overriddenClass(method);
- if (overriddenClass != null) {
- for (int i = 0; i < methlist.size(); i++) {
- TypeElement te = utils.getEnclosingTypeElement(methlist.get(i));
- if (te == overriddenClass || utils.isSubclassOf(overriddenClass, te)) {
- methlist.remove(i); // remove overridden method
- return;
- }
- }
- }
- }
-
- /**
- * Search in the already found methods' list and check if it contains
- * a method which is overriding the method parameter or is the method
- * parameter itself.
- *
- * @param method MethodDoc Method to be searched in the Method List for
- * an overriding method.
- */
- private boolean overridingMethodFound(ExecutableElement method) {
- TypeElement containingClass = utils.getEnclosingTypeElement(method);
- for (ExecutableElement listmethod : methlist) {
- if (containingClass == utils.getEnclosingTypeElement(listmethod)) {
- // it's the same method.
- return true;
- }
- TypeElement te = utils.overriddenClass(listmethod);
- if (te == null) {
- continue;
- }
- if (te == containingClass || utils.isSubclassOf(te, containingClass)) {
- return true;
- }
- }
- return false;
- }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -35,7 +35,8 @@
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Messages;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
/**
* Build the mapping of each Unicode character with it's member lists
@@ -165,8 +166,8 @@
protected void putMembersInIndexMap(TypeElement te) {
adjustIndexMap(utils.getAnnotationFields(te));
adjustIndexMap(utils.getFields(te));
- VisibleMemberMap vmm = configuration.getVisibleMemberMap(te, Kind.METHODS);
- adjustIndexMap(vmm.getMembers(te));
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
+ adjustIndexMap(vmt.getMembers(METHODS));
adjustIndexMap(utils.getConstructors(te));
adjustIndexMap(utils.getEnumConstants(te));
}
@@ -216,7 +217,7 @@
* Should this element be added to the index map?
*/
protected boolean shouldAddToIndexMap(Element element) {
- if (utils.isHidden(element)) {
+ if (utils.hasHiddenTag(element)) {
return false;
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Thu Apr 26 17:59:02 2018 +0200
@@ -74,12 +74,10 @@
import com.sun.source.doctree.DocTree.Kind;
import com.sun.source.doctree.ParamTree;
import com.sun.source.doctree.SerialFieldTree;
-import com.sun.source.doctree.StartElementTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.LineMap;
import com.sun.source.util.DocSourcePositions;
import com.sun.source.util.DocTrees;
-import com.sun.source.util.SimpleDocTreeVisitor;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.model.JavacTypes;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
@@ -95,7 +93,6 @@
import static com.sun.source.doctree.DocTree.Kind.*;
import static jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.MAX_CONSTANT_VALUE_INDEX_LENGTH;
-
/**
* Utilities Class for Doclets.
*
@@ -806,9 +803,8 @@
if (te == null) {
return null;
}
- VisibleMemberMap vmm = configuration.getVisibleMemberMap(te,
- VisibleMemberMap.Kind.METHODS);
- for (Element e : vmm.getMembers(te)) {
+ VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
+ for (Element e : vmt.getMembers(VisibleMemberTable.Kind.METHODS)) {
ExecutableElement ee = (ExecutableElement)e;
if (configuration.workArounds.overrides(method, ee, origin) &&
!isSimpleOverride(ee)) {
@@ -1167,7 +1163,7 @@
}
TypeElement superClass = asTypeElement(superType);
// skip "hidden" classes
- while ((superClass != null && isHidden(superClass))
+ while ((superClass != null && hasHiddenTag(superClass))
|| (superClass != null && !isPublic(superClass) && !isLinkable(superClass))) {
TypeMirror supersuperType = superClass.getSuperclass();
TypeElement supersuperClass = asTypeElement(supersuperType);
@@ -1416,7 +1412,7 @@
* @param e the queried element
* @return true if it exists, false otherwise
*/
- public boolean isHidden(Element e) {
+ public boolean hasHiddenTag(Element e) {
// prevent needless tests on elements which are not included
if (!isIncluded(e)) {
return false;
@@ -1462,14 +1458,14 @@
new TreeSet<>(makeGeneralPurposeComparator());
if (!javafx) {
for (Element te : classlist) {
- if (!isHidden(te)) {
+ if (!hasHiddenTag(te)) {
filteredOutClasses.add((TypeElement)te);
}
}
return filteredOutClasses;
}
for (Element e : classlist) {
- if (isPrivate(e) || isPackagePrivate(e) || isHidden(e)) {
+ if (isPrivate(e) || isPackagePrivate(e) || hasHiddenTag(e)) {
continue;
}
filteredOutClasses.add((TypeElement)e);
@@ -2246,18 +2242,6 @@
return convertToTypeElement(getItems(e, false, INTERFACE));
}
- List<Element> getNestedClasses(TypeElement e) {
- List<Element> result = new ArrayList<>();
- recursiveGetItems(result, e, true, CLASS);
- return result;
- }
-
- List<Element> getNestedClassesUnfiltered(TypeElement e) {
- List<Element> result = new ArrayList<>();
- recursiveGetItems(result, e, false, CLASS);
- return result;
- }
-
public List<Element> getEnumConstants(Element e) {
return getItems(e, true, ENUM_CONSTANT);
}
@@ -2381,7 +2365,6 @@
}
EnumSet<ElementKind> nestedKinds = EnumSet.of(ANNOTATION_TYPE, CLASS, ENUM, INTERFACE);
-
void recursiveGetItems(Collection<Element> list, Element e, boolean filter, ElementKind... select) {
list.addAll(getItems0(e, filter, select));
List<Element> classes = getItems0(e, filter, nestedKinds);
@@ -2411,7 +2394,8 @@
}
private SimpleElementVisitor9<Boolean, Void> shouldDocumentVisitor = null;
- private boolean shouldDocument(Element e) {
+
+ protected boolean shouldDocument(Element e) {
if (shouldDocumentVisitor == null) {
shouldDocumentVisitor = new SimpleElementVisitor9<Boolean, Void>() {
private boolean hasSource(TypeElement e) {
@@ -2422,6 +2406,10 @@
// handle types
@Override
public Boolean visitType(TypeElement e, Void p) {
+ // treat inner classes etc as members
+ if (e.getNestingKind().isNested()) {
+ return defaultAction(e, p);
+ }
return configuration.docEnv.isSelected(e) && hasSource(e);
}
@@ -3273,5 +3261,11 @@
this.first = first;
this.second = second;
}
+
+ public String toString() {
+ StringBuffer out = new StringBuffer();
+ out.append(first + ":" + second);
+ return out.toString();
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberCache.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.toolkit.util;
+
+import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * This class manages the visible member table for each type element.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+
+public class VisibleMemberCache {
+ private final Map<TypeElement, VisibleMemberTable> cache;
+ private final BaseConfiguration configuration;
+
+ public VisibleMemberCache(BaseConfiguration configuration) {
+ this.configuration = configuration;
+ cache = new HashMap<>();
+ }
+
+ public VisibleMemberTable getVisibleMemberTable(TypeElement te) {
+ return cache.computeIfAbsent(te, t -> new VisibleMemberTable(t, configuration, this));
+ }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,842 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.*;
-import java.util.regex.Pattern;
-
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-
-import com.sun.source.doctree.DocCommentTree;
-import com.sun.source.doctree.DocTree;
-
-import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-import jdk.javadoc.internal.doclets.toolkit.Messages;
-
-/**
- * A data structure that encapsulates the visible members of a particular
- * type for a given class tree. To use this data structure, you must specify
- * the type of member you are interested in (nested class, field, constructor
- * or method) and the leaf of the class tree. The data structure will map
- * all visible members in the leaf and classes above the leaf in the tree.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- * @author Jamie Ho (rewrite)
- */
-public class VisibleMemberMap {
-
- private boolean noVisibleMembers = true;
-
- public static enum Kind {
- INNER_CLASSES,
- ENUM_CONSTANTS,
- FIELDS,
- CONSTRUCTORS,
- METHODS,
- ANNOTATION_TYPE_FIELDS,
- ANNOTATION_TYPE_MEMBER_OPTIONAL,
- ANNOTATION_TYPE_MEMBER_REQUIRED,
- PROPERTIES;
-
- public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
- public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
- public static String getNavLinkLabels(Kind kind) {
- switch (kind) {
- case INNER_CLASSES:
- return "doclet.navNested";
- case ENUM_CONSTANTS:
- return "doclet.navEnum";
- case FIELDS:
- return "doclet.navField";
- case CONSTRUCTORS:
- return "doclet.navConstructor";
- case METHODS:
- return "doclet.navMethod";
- default:
- throw new AssertionError("unknown kind:" + kind);
- }
- }
- }
-
- public static final String STARTLEVEL = "start";
-
- // properties aren't named setA* or getA*
- private static final Pattern GETTERSETTERPATTERN = Pattern.compile("[sg]et\\p{Upper}.*");
- /**
- * List of TypeElement objects for which ClassMembers objects are built.
- */
- private final Set<TypeElement> visibleClasses;
-
- /**
- * Map for each member name on to a map which contains members with same
- * name-signature. The mapped map will contain mapping for each MemberDoc
- * onto it's respecive level string.
- */
- private final Map<Object, Map<Element, String>> memberNameMap = new HashMap<>();
-
- /**
- * Map of class and it's ClassMembers object.
- */
- private final Map<TypeElement, ClassMembers> classMap = new HashMap<>();
-
- /**
- * Type whose visible members are requested. This is the leaf of
- * the class tree being mapped.
- */
- private final TypeElement typeElement;
-
- /**
- * Member kind: InnerClasses/Fields/Methods?
- */
- public final Kind kind;
-
- /**
- * The configuration this VisibleMemberMap was created with.
- */
- private final BaseConfiguration configuration;
- private final Messages messages;
- private final Utils utils;
- private final Comparator<Element> comparator;
-
- private final Map<TypeElement, List<Element>> propertiesCache;
- private final Map<Element, Element> classPropertiesMap;
- private final Map<Element, GetterSetter> getterSetterMap;
-
- /**
- * Construct a VisibleMemberMap of the given type for the given class.
- *
- * @param typeElement whose members are being mapped.
- * @param kind the kind of member that is being mapped.
- * @param configuration the configuration to use to construct this
- * VisibleMemberMap. If the field configuration.nodeprecated is true the
- * deprecated members are excluded from the map. If the field
- * configuration.javafx is true the JavaFX features are used.
- */
- public VisibleMemberMap(TypeElement typeElement,
- Kind kind,
- BaseConfiguration configuration) {
- this.typeElement = typeElement;
- this.kind = kind;
- this.configuration = configuration;
- this.messages = configuration.getMessages();
- this.utils = configuration.utils;
- propertiesCache = configuration.propertiesCache;
- classPropertiesMap = configuration.classPropertiesMap;
- getterSetterMap = configuration.getterSetterMap;
- comparator = utils.makeGeneralPurposeComparator();
- visibleClasses = new LinkedHashSet<>();
- new ClassMembers(typeElement, STARTLEVEL).build();
- }
-
- /**
- * Return the list of visible classes in this map.
- *
- * @return the list of visible classes in this map.
- */
- public SortedSet<TypeElement> getVisibleClasses() {
- SortedSet<TypeElement> vClasses = new TreeSet<>(comparator);
- vClasses.addAll(visibleClasses);
- return vClasses;
- }
-
- /**
- * Returns the first method where the given method is visible.
- * @param e the method whose visible enclosing type is to be found.
- * @return the method found or null
- */
- public ExecutableElement getVisibleMethod(ExecutableElement e) {
- if (kind != Kind.METHODS || e.getKind() != ElementKind.METHOD) {
- throw new AssertionError("incompatible member type or visible member map" + e);
- }
- // start with the current class
- for (Element m : getMembers(typeElement)) {
- ExecutableElement mthd = (ExecutableElement)m;
- if (utils.executableMembersEqual(mthd, e)) {
- return mthd;
- }
- }
-
- for (TypeElement te : visibleClasses) {
- if (te == typeElement)
- continue;
- for (Element m : getMembers(te)) {
- ExecutableElement mthd = (ExecutableElement)m;
- if (utils.executableMembersEqual(mthd, e)) {
- return mthd;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the property field documentation belonging to the given member.
- * @param element the member for which the property documentation is needed.
- * @return the property field documentation, null if there is none.
- */
- public Element getPropertyElement(Element element) {
- return classPropertiesMap.get(element);
- }
-
- /**
- * Returns the getter documentation belonging to the given property method.
- * @param propertyMethod the method for which the getter is needed.
- * @return the getter documentation, null if there is none.
- */
- public Element getGetterForProperty(Element propertyMethod) {
- return getterSetterMap.get(propertyMethod).getGetter();
- }
-
- /**
- * Returns the setter documentation belonging to the given property method.
- * @param propertyMethod the method for which the setter is needed.
- * @return the setter documentation, null if there is none.
- */
- public Element getSetterForProperty(Element propertyMethod) {
- return getterSetterMap.get(propertyMethod).getSetter();
- }
-
- /**
- * Return the package private members inherited by the class. Only return
- * if parent is package private and not documented.
- *
- * @return the package private members inherited by the class.
- */
- private List<Element> getInheritedPackagePrivateMethods() {
- List<Element> results = new ArrayList<>();
- for (TypeElement currentClass : visibleClasses) {
- if (currentClass != typeElement &&
- utils.isPackagePrivate(currentClass) &&
- !utils.isLinkable(currentClass)) {
- // Document these members in the child class because
- // the parent is inaccessible.
- results.addAll(classMap.get(currentClass).members);
- }
- }
- return results;
- }
-
- /**
- * Returns a list of visible enclosed members of the mapped type element.
- *
- * In the case of methods, the list may contain those methods that are
- * extended with no specification changes as indicated by the existence
- * of a sole @inheritDoc or devoid of any API commments.
- *
- * This list may also contain appended members, inherited by inaccessible
- * super types. These members are documented in the subtype when the
- * super type is not documented.
- *
- * @return a list of visible enclosed members
- */
-
- public List<Element> getLeafMembers() {
- List<Element> result = new ArrayList<>();
- result.addAll(getMembers(typeElement));
- result.addAll(getInheritedPackagePrivateMethods());
- return result;
- }
-
- // Cache to improve performance
- private HashMap<ExecutableElement, Boolean> overridenMethodCache = new HashMap<>();
-
- private boolean hasOverridden(ExecutableElement method) {
- return overridenMethodCache.computeIfAbsent(method, m -> hasOverriddenCompute(m));
- }
-
- private boolean hasOverriddenCompute(ExecutableElement method) {
- if (kind != Kind.METHODS) {
- throw new AssertionError("Unexpected kind: " + kind);
- }
- for (TypeElement t : visibleClasses) {
- for (Element member : classMap.get(t).members) {
- ExecutableElement inheritedMethod = (ExecutableElement)member;
- if (utils.elementUtils.overrides(method, inheritedMethod, t)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns a list of enclosed members for the given type.
- *
- * @param typeElement the given type
- *
- * @return a list of enclosed members
- */
- public List<Element> getMembers(TypeElement typeElement) {
- List<Element> result = new ArrayList<>();
- if (this.kind == Kind.METHODS) {
- for (Element member : classMap.get(typeElement).members) {
- ExecutableElement method = (ExecutableElement)member;
- if (hasOverridden(method)) {
- if (!utils.isSimpleOverride(method)) {
- result.add(method);
- }
- } else {
- result.add(method);
- }
- }
- } else {
- result.addAll(classMap.get(typeElement).members);
- }
- return result;
- }
-
- public boolean hasMembers(TypeElement typeElement) {
- return !classMap.get(typeElement).members.isEmpty();
- }
-
- private void fillMemberLevelMap(List<? extends Element> list, String level) {
- for (Element element : list) {
- Object key = getMemberKey(element);
- Map<Element, String> memberLevelMap = memberNameMap.get(key);
- if (memberLevelMap == null) {
- memberLevelMap = new HashMap<>();
- memberNameMap.put(key, memberLevelMap);
- }
- memberLevelMap.put(element, level);
- }
- }
-
- private void purgeMemberLevelMap(Iterable<? extends Element> list, String level) {
- for (Element element : list) {
- Object key = getMemberKey(element);
- Map<Element, String> memberLevelMap = memberNameMap.get(key);
- if (memberLevelMap != null && level.equals(memberLevelMap.get(element)))
- memberLevelMap.remove(element);
- }
- }
-
- /**
- * Represents a class member.
- */
- private class ClassMember {
- private Set<Element> members;
-
- public ClassMember(Element element) {
- members = new HashSet<>();
- members.add(element);
- }
-
- public boolean isEqual(ExecutableElement method) {
- for (Element member : members) {
- if (member.getKind() != ElementKind.METHOD)
- continue;
- ExecutableElement thatMethod = (ExecutableElement) member;
- if (utils.executableMembersEqual(method, thatMethod) &&
- !utils.isSimpleOverride(thatMethod)) {
- members.add(method);
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * A data structure that represents the class members for
- * a visible class.
- */
- private class ClassMembers {
-
- /**
- * The mapping class, whose inherited members are put in the
- * {@link #members} list.
- */
- private final TypeElement typeElement;
-
- /**
- * List of members from the mapping class.
- */
- private List<Element> members = null;
-
- /**
- * Level/Depth of inheritance.
- */
- private final String level;
-
- private ClassMembers(TypeElement mappingClass, String level) {
- this.typeElement = mappingClass;
- this.level = level;
- if (classMap.containsKey(mappingClass) &&
- level.startsWith(classMap.get(mappingClass).level)) {
- //Remove lower level class so that it can be replaced with
- //same class found at higher level.
- purgeMemberLevelMap(getClassMembers(mappingClass, false),
- classMap.get(mappingClass).level);
- classMap.remove(mappingClass);
- visibleClasses.remove(mappingClass);
- }
- if (!classMap.containsKey(mappingClass)) {
- classMap.put(mappingClass, this);
- visibleClasses.add(mappingClass);
- }
- }
-
- private void build() {
- if (kind == Kind.CONSTRUCTORS) {
- addMembers(typeElement);
- } else {
- mapClass();
- }
- }
-
- private void mapClass() {
- addMembers(typeElement);
- List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
- for (TypeMirror anInterface : interfaces) {
- String locallevel = level + 1;
- ClassMembers cm = new ClassMembers(utils.asTypeElement(anInterface), locallevel);
- cm.mapClass();
- }
- if (utils.isClass(typeElement)) {
- TypeElement superclass = utils.getSuperClass(typeElement);
- if (!(superclass == null || typeElement.equals(superclass))) {
- ClassMembers cm = new ClassMembers(superclass, level + "c");
- cm.mapClass();
- }
- }
- }
-
- /**
- * Get all the valid members from the mapping class. Get the list of
- * members for the class to be included into(ctii), also get the level
- * string for ctii. If mapping class member is not already in the
- * inherited member list and if it is visible in the ctii and not
- * overridden, put such a member in the inherited member list.
- * Adjust member-level-map, class-map.
- */
- private void addMembers(TypeElement fromClass) {
- List<Element> result = new ArrayList<>();
- for (Element element : getClassMembers(fromClass, true)) {
- if (memberIsVisible(element)) {
- if (!isOverridden(element, level)) {
- if (!utils.isHidden(element)) {
- result.add(element);
- }
- }
- }
- }
- if (members != null) {
- throw new AssertionError("members should not be null");
- }
- members = Collections.unmodifiableList(result);
- if (!members.isEmpty()) {
- noVisibleMembers = false;
- }
- fillMemberLevelMap(getClassMembers(fromClass, false), level);
- }
-
- /**
- * Is given element visible in given typeElement in terms of inheritance? The given element
- * is visible in the given typeElement if it is public or protected and if it is
- * package-private if it's containing class is in the same package as the given typeElement.
- */
- private boolean memberIsVisible(Element element) {
- if (utils.getEnclosingTypeElement(element).equals(VisibleMemberMap.this.typeElement)) {
- //Member is in class that we are finding visible members for.
- //Of course it is visible.
- return true;
- } else if (utils.isPrivate(element)) {
- //Member is in super class or implemented interface.
- //Private, so not inherited.
- return false;
- } else if (utils.isPackagePrivate(element)) {
- //Member is package private. Only return true if its class is in
- //same package.
- return utils.containingPackage(element).equals(utils.containingPackage(VisibleMemberMap.this.typeElement));
- } else {
- //Public members are always inherited.
- return true;
- }
- }
-
- /**
- * Return all available class members.
- */
- private List<? extends Element> getClassMembers(TypeElement te, boolean filter) {
- if (utils.isEnum(te) && kind == Kind.CONSTRUCTORS) {
- //If any of these rules are hit, return empty array because
- //we don't document these members ever.
- return Collections.emptyList();
- }
- List<? extends Element> list;
- switch (kind) {
- case ANNOTATION_TYPE_FIELDS:
- list = (filter)
- ? utils.getAnnotationFields(te)
- : utils.getAnnotationFieldsUnfiltered(te);
- break;
- case ANNOTATION_TYPE_MEMBER_OPTIONAL:
- list = utils.isAnnotationType(te)
- ? filterAnnotations(te, false)
- : Collections.emptyList();
- break;
- case ANNOTATION_TYPE_MEMBER_REQUIRED:
- list = utils.isAnnotationType(te)
- ? filterAnnotations(te, true)
- : Collections.emptyList();
- break;
- case INNER_CLASSES:
- List<TypeElement> xlist = filter
- ? utils.getInnerClasses(te)
- : utils.getInnerClassesUnfiltered(te);
- list = new ArrayList<>(xlist);
- break;
- case ENUM_CONSTANTS:
- list = utils.getEnumConstants(te);
- break;
- case FIELDS:
- if (filter) {
- list = utils.isAnnotationType(te)
- ? utils.getAnnotationFields(te)
- : utils.getFields(te);
- } else {
- list = utils.isAnnotationType(te)
- ? utils.getAnnotationFieldsUnfiltered(te)
- : utils.getFieldsUnfiltered(te);
- }
- break;
- case CONSTRUCTORS:
- list = utils.getConstructors(te);
- break;
- case METHODS:
- list = filter ? utils.getMethods(te) : utils.getMethodsUnfiltered(te);
- checkOnPropertiesTags(list);
- break;
- case PROPERTIES:
- list = properties(te, filter);
- break;
- default:
- list = Collections.emptyList();
- }
- // Deprected members should be excluded or not?
- if (configuration.nodeprecated) {
- return utils.excludeDeprecatedMembers(list);
- }
- return list;
- }
-
- /**
- * Filter the annotation type members and return either the required
- * members or the optional members, depending on the value of the
- * required parameter.
- *
- * @param typeElement The annotation type to process.
- * @param required
- * @return the annotation type members and return either the required
- * members or the optional members, depending on the value of the
- * required parameter.
- */
- private List<Element> filterAnnotations(TypeElement typeElement, boolean required) {
- List<Element> members = utils.getAnnotationMethods(typeElement);
- List<Element> targetMembers = new ArrayList<>();
- for (Element member : members) {
- ExecutableElement ee = (ExecutableElement)member;
- if ((required && ee.getDefaultValue() == null)
- || ((!required) && ee.getDefaultValue() != null)) {
- targetMembers.add(member);
- }
- }
- return targetMembers;
- }
-
- /**
- * Is member overridden? The member is overridden if it is found in the
- * same level hierarchy e.g. member at level "11" overrides member at
- * level "111".
- */
- private boolean isOverridden(Element element, String level) {
- Object key = getMemberKey(element);
- Map<?, String> memberLevelMap = (Map<?, String>) memberNameMap.get(key);
- if (memberLevelMap == null)
- return false;
- for (String mappedlevel : memberLevelMap.values()) {
- if (mappedlevel.equals(STARTLEVEL)
- || (level.startsWith(mappedlevel)
- && !level.equals(mappedlevel))) {
- return true;
- }
- }
- return false;
- }
-
- private List<Element> properties(final TypeElement typeElement, final boolean filter) {
- final List<ExecutableElement> allMethods = filter
- ? utils.getMethods(typeElement)
- : utils.getMethodsUnfiltered(typeElement);
- final List<VariableElement> allFields = utils.getFieldsUnfiltered(typeElement);
-
- if (propertiesCache.containsKey(typeElement)) {
- return propertiesCache.get(typeElement);
- }
-
- final List<Element> result = new ArrayList<>();
-
- for (final Element propertyMethod : allMethods) {
- ExecutableElement ee = (ExecutableElement)propertyMethod;
- if (!isPropertyMethod(ee)) {
- continue;
- }
-
- final ExecutableElement getter = getterForField(allMethods, ee);
- final ExecutableElement setter = setterForField(allMethods, ee);
- final VariableElement field = fieldForProperty(allFields, ee);
-
- addToPropertiesMap(setter, getter, ee, field);
- getterSetterMap.put(propertyMethod, new GetterSetter(getter, setter));
- result.add(ee);
- }
- propertiesCache.put(typeElement, result);
- return result;
- }
-
- private void addToPropertiesMap(ExecutableElement setter,
- ExecutableElement getter,
- ExecutableElement propertyMethod,
- VariableElement field) {
- if (field == null || utils.getDocCommentTree(field) == null) {
- addToPropertiesMap(setter, propertyMethod);
- addToPropertiesMap(getter, propertyMethod);
- addToPropertiesMap(propertyMethod, propertyMethod);
- } else {
- addToPropertiesMap(getter, field);
- addToPropertiesMap(setter, field);
- addToPropertiesMap(propertyMethod, field);
- }
- }
-
- private void addToPropertiesMap(Element propertyMethod,
- Element commentSource) {
- if (null == propertyMethod || null == commentSource) {
- return;
- }
- DocCommentTree docTree = utils.getDocCommentTree(propertyMethod);
-
- /* The second condition is required for the property buckets. In
- * this case the comment is at the property method (not at the field)
- * and it needs to be listed in the map.
- */
- if ((docTree == null) || propertyMethod.equals(commentSource)) {
- classPropertiesMap.put(propertyMethod, commentSource);
- }
- }
-
- private ExecutableElement getterForField(List<ExecutableElement> methods,
- ExecutableElement propertyMethod) {
- final String propertyMethodName = utils.getSimpleName(propertyMethod);
- final String fieldName = propertyMethodName.substring(0,
- propertyMethodName.lastIndexOf("Property"));
- final String fieldNameUppercased =
- "" + Character.toUpperCase(fieldName.charAt(0))
- + fieldName.substring(1);
- final String getterNamePattern;
- final String fieldTypeName = propertyMethod.getReturnType().toString();
- if ("boolean".equals(fieldTypeName)
- || fieldTypeName.endsWith("BooleanProperty")) {
- getterNamePattern = "(is|get)" + fieldNameUppercased;
- } else {
- getterNamePattern = "get" + fieldNameUppercased;
- }
-
- for (ExecutableElement method : methods) {
- if (Pattern.matches(getterNamePattern, utils.getSimpleName(method))) {
- if (method.getParameters().isEmpty() &&
- utils.isPublic(method) || utils.isProtected(method)) {
- return method;
- }
- }
- }
- return null;
- }
-
- private ExecutableElement setterForField(List<ExecutableElement> methods,
- ExecutableElement propertyMethod) {
- final String propertyMethodName = utils.getSimpleName(propertyMethod);
- final String fieldName =
- propertyMethodName.substring(0,
- propertyMethodName.lastIndexOf("Property"));
- final String fieldNameUppercased =
- "" + Character.toUpperCase(fieldName.charAt(0))
- + fieldName.substring(1);
- final String setter = "set" + fieldNameUppercased;
-
- for (ExecutableElement method : methods) {
- if (setter.equals(utils.getSimpleName(method))) {
- if (method.getParameters().size() == 1
- && method.getReturnType().getKind() == TypeKind.VOID
- && (utils.isPublic(method) || utils.isProtected(method))) {
- return method;
- }
- }
- }
- return null;
- }
-
- private VariableElement fieldForProperty(List<VariableElement> fields, ExecutableElement property) {
-
- for (VariableElement field : fields) {
- final String fieldName = utils.getSimpleName(field);
- final String propertyName = fieldName + "Property";
- if (propertyName.equals(utils.getSimpleName(property))) {
- return field;
- }
- }
- return null;
- }
-
- private boolean isPropertyMethod(ExecutableElement method) {
- if (!configuration.javafx) {
- return false;
- }
- if (!utils.getSimpleName(method).endsWith("Property")) {
- return false;
- }
-
- if (!memberIsVisible(method)) {
- return false;
- }
-
- if (GETTERSETTERPATTERN.matcher(utils.getSimpleName(method)).matches()) {
- return false;
- }
- if (!method.getTypeParameters().isEmpty()) {
- return false;
- }
- return method.getParameters().isEmpty()
- && method.getReturnType().getKind() != TypeKind.VOID;
- }
-
- private void checkOnPropertiesTags(List<? extends Element> members) {
- for (Element e: members) {
- ExecutableElement ee = (ExecutableElement)e;
- if (utils.isIncluded(ee)) {
- CommentHelper ch = utils.getCommentHelper(ee);
- for (DocTree tree: utils.getBlockTags(ee)) {
- String tagName = ch.getTagName(tree);
- if (tagName.equals("@propertySetter")
- || tagName.equals("@propertyGetter")
- || tagName.equals("@propertyDescription")) {
- if (!isPropertyGetterOrSetter(members, ee)) {
- messages.warning(ch.getDocTreePath(tree),
- "doclet.javafx_tag_misuse");
- }
- break;
- }
- }
- }
- }
- }
-
- private boolean isPropertyGetterOrSetter(List<? extends Element> members,
- ExecutableElement method) {
- String propertyName = utils.propertyName(method);
- if (!propertyName.isEmpty()) {
- String propertyMethodName = propertyName + "Property";
- for (Element member: members) {
- if (utils.getSimpleName(member).equals(propertyMethodName)) {
- return true;
- }
- }
- }
- return false;
- }
- }
-
- public class GetterSetter {
- private final Element getter;
- private final Element setter;
-
- public GetterSetter(Element getter, Element setter) {
- this.getter = getter;
- this.setter = setter;
- }
-
- public Element getGetter() {
- return getter;
- }
-
- public Element getSetter() {
- return setter;
- }
- }
-
- /**
- * Return true if this map has no visible members.
- *
- * @return true if this map has no visible members.
- */
- public boolean noVisibleMembers() {
- return noVisibleMembers;
- }
-
- private ClassMember getClassMember(ExecutableElement member) {
- for (Object key : memberNameMap.keySet()) {
- if (key instanceof String) {
- continue;
- }
- if (((ClassMember) key).isEqual(member)) {
- return (ClassMember) key;
- }
- }
- return new ClassMember(member);
- }
-
- /**
- * Return the key to the member map for the given member.
- */
- private Object getMemberKey(Element element) {
- if (utils.isConstructor(element)) {
- return utils.getSimpleName(element) + utils.flatSignature((ExecutableElement)element);
- } else if (utils.isMethod(element)) {
- return getClassMember((ExecutableElement) element);
- } else if (utils.isField(element) || utils.isEnumConstant(element) || utils.isAnnotationType(element)) {
- return utils.getSimpleName(element);
- } else { // it's a class or interface
- String classOrIntName = utils.getSimpleName(element);
- //Strip off the containing class name because we only want the member name.
- classOrIntName = classOrIntName.indexOf('.') != 0
- ? classOrIntName.substring(classOrIntName.lastIndexOf('.'))
- : classOrIntName;
- return "clint" + classOrIntName;
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,992 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.toolkit.util;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.SimpleElementVisitor9;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
+import jdk.javadoc.internal.doclets.toolkit.PropertyUtils;
+
+/**
+ * This class computes the main data structure for the doclet's
+ * operations. Essentially, the implementation encapsulating the
+ * javax.lang.models view of what can be documented about a
+ * type element's members.
+ * <p>
+ * The general operations are as follows:
+ * <p>
+ * Members: these are the members from jx.l.m's view but
+ * are structured along the kinds of this class.
+ * <p>
+ * Extra Members: these are members enclosed in an undocumented
+ * package-private type element, and may not be linkable (or documented),
+ * however, the members of such a type element may be documented, as if
+ * declared in the sub type, only if the enclosing type is not being
+ * documented by a filter such as -public, -protected, etc.
+ * <p>
+ * Visible Members: these are the members that are "visible"
+ * and available and should be documented, in a type element.
+ * <p>
+ * The basic rule for computation: when considering a type element,
+ * besides its immediate direct types and interfaces, the computation
+ * should not expand to any other type in the inheritance hierarchy.
+ * <p>
+ * This table generates all the data structures it needs for each
+ * type, as its own view, and will present some form of this to the
+ * doclet as and when required to.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ *
+ */
+
+public class VisibleMemberTable {
+
+ public enum Kind {
+ INNER_CLASSES,
+ ENUM_CONSTANTS,
+ FIELDS,
+ CONSTRUCTORS,
+ METHODS,
+ ANNOTATION_TYPE_FIELDS,
+ ANNOTATION_TYPE_MEMBER_OPTIONAL,
+ ANNOTATION_TYPE_MEMBER_REQUIRED,
+ PROPERTIES;
+
+ public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
+ public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
+ }
+
+ final TypeElement te;
+ final TypeElement parent;
+
+ final BaseConfiguration config;
+ final Utils utils;
+ final VisibleMemberCache mcache;
+
+ private List<VisibleMemberTable> allSuperclasses;
+ private List<VisibleMemberTable> allSuperinterfaces;
+ private List<VisibleMemberTable> parents;
+
+
+ private Map<Kind, List<Element>> extraMembers = new EnumMap<>(Kind.class);
+ private Map<Kind, List<Element>> visibleMembers = null;
+ private Map<ExecutableElement, PropertyMembers> propertyMap = new HashMap<>();
+
+ // Keeps track of method overrides
+ Map<ExecutableElement, OverridingMethodInfo> overriddenMethodTable
+ = new LinkedHashMap<>();
+
+ protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration,
+ VisibleMemberCache mcache) {
+ config = configuration;
+ utils = configuration.utils;
+ te = typeElement;
+ parent = utils.getSuperClass(te);
+ this.mcache = mcache;
+ allSuperclasses = new ArrayList<>();
+ allSuperinterfaces = new ArrayList<>();
+ parents = new ArrayList<>();
+ }
+
+ private synchronized void ensureInitialized() {
+ if (visibleMembers != null)
+ return;
+
+ visibleMembers = new EnumMap<>(Kind.class);
+ for (Kind kind : Kind.values()) {
+ visibleMembers.put(kind, new ArrayList<>());
+ }
+ computeParents();
+ computeVisibleMembers();
+ }
+
+ List<? extends Element> getExtraMembers(Kind kind) {
+ ensureInitialized();
+ return visibleMembers.getOrDefault(kind, Collections.emptyList());
+ }
+
+ List<VisibleMemberTable> getAllSuperclasses() {
+ ensureInitialized();
+ return allSuperclasses;
+ }
+
+ List<VisibleMemberTable> getAllSuperinterfaces() {
+ ensureInitialized();
+ return allSuperinterfaces;
+ }
+
+ /**
+ * Returns a list of all visible enclosed members of a type element,
+ * and inherited members.
+ * <p>
+ * Notes:
+ * a. The list may or may not contain simple overridden methods.
+ * A simple overridden method is one that overrides a super method
+ * with no specification changes as indicated by the existence of a
+ * sole @inheritDoc or devoid of any API commments.
+ * <p>
+ * b.The list may contain (extra) members, inherited by inaccessible
+ * super types, primarily package private types. These members are
+ * required to be documented in the subtype when the super type is
+ * not documented.
+ *
+ * @param kind the member kind
+ * @return a list of all visible members
+ */
+ public List<? extends Element> getAllVisibleMembers(Kind kind) {
+ ensureInitialized();
+ return visibleMembers.getOrDefault(kind, Collections.emptyList());
+ }
+
+ /**
+ * Returns a list of visible enclosed members of a specified kind,
+ * filtered by the specified predicate.
+ * @param kind the member kind
+ * @param p the predicate used to filter the output
+ * @return a list of visible enclosed members
+ */
+ public List<? extends Element> getVisibleMembers(Kind kind, Predicate<Element> p) {
+ ensureInitialized();
+
+ return visibleMembers.getOrDefault(kind, Collections.emptyList()).stream()
+ .filter(p)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Returns a list of all enclosed members including any extra members.
+ * Typically called by various builders.
+ *
+ * @param kind the member kind
+ * @return a list of visible enclosed members
+ */
+ public List<? extends Element> getVisibleMembers(Kind kind) {
+ Predicate<Element> declaredAndLeafMembers = e -> {
+ TypeElement encl = utils.getEnclosingTypeElement(e);
+ return encl == te || isUndocumentedEnclosure(encl);
+ };
+ return getVisibleMembers(kind, declaredAndLeafMembers);
+ }
+
+ /**
+ * Returns a list of visible enclosed members of given kind,
+ * declared in this type element, and does not include
+ * any inherited members or extra members.
+ *
+ * @return a list of visible enclosed members in this type
+ */
+ public List<? extends Element> getMembers(Kind kind) {
+ Predicate<Element> onlyLocallyDeclaredMembers = e -> utils.getEnclosingTypeElement(e) == te;
+ return getVisibleMembers(kind, onlyLocallyDeclaredMembers);
+ }
+
+ /**
+ * Returns the overridden method, if it is simply overridding or the
+ * method is a member of a package private type, this method is
+ * primarily used to determine the location of a possible comment.
+ *
+ * @param e the method to check
+ * @return the method found or null
+ */
+ public ExecutableElement getOverriddenMethod(ExecutableElement e) {
+ ensureInitialized();
+
+ OverridingMethodInfo found = overriddenMethodTable.get(e);
+ if (found != null && (found.simpleOverride || isUndocumentedEnclosure(utils.getEnclosingTypeElement(e)))) {
+ return found.overrider;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the simply overridden method.
+ * @param e the method to check
+ * @return the overridden method or null
+ */
+ public ExecutableElement getsimplyOverriddenMethod(ExecutableElement e) {
+ ensureInitialized();
+
+ OverridingMethodInfo found = overriddenMethodTable.get(e);
+ if (found != null && found.simpleOverride) {
+ return found.overrider;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a set of visible type elements in this type element's lineage.
+ * <p>
+ * This method returns the super-types in the inheritance
+ * order C, B, A, j.l.O. The super-interfaces however are
+ * alpha sorted and appended to the resulting set.
+ *
+ * @return the list of visible classes in this map.
+ */
+ public Set<TypeElement> getVisibleTypeElements() {
+ ensureInitialized();
+ Set<TypeElement> result = new LinkedHashSet<>();
+
+ // Add this type element first.
+ result.add(te);
+
+ // Add the super classes.
+ allSuperclasses.stream()
+ .map(vmt -> vmt.te)
+ .forEach(result::add);
+
+ // ... and finally the sorted super interfaces.
+ allSuperinterfaces.stream()
+ .map(vmt -> vmt.te)
+ .sorted(utils.makeGeneralPurposeComparator())
+ .forEach(result::add);
+
+ return result;
+ }
+
+ /**
+ * Returns true if this table contains visible members.
+ *
+ * @return true if visible members are present.
+ */
+ public boolean hasVisibleMembers() {
+ for (Kind kind : Kind.values()) {
+ if (hasVisibleMembers(kind))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if this table contains visible members of
+ * the specified kind, including inhertied members.
+ *
+ * @return true if visible members are present.
+ */
+ public boolean hasVisibleMembers(Kind kind) {
+ ensureInitialized();
+ List<Element> elements = visibleMembers.get(kind);
+ return elements != null && !elements.isEmpty();
+ }
+
+ /**
+ * Returns the property field associated with the property method.
+ * @param propertyMethod the identifying property method
+ * @return the field or null if absent
+ */
+ public VariableElement getPropertyField(ExecutableElement propertyMethod) {
+ ensureInitialized();
+ PropertyMembers pm = propertyMap.get(propertyMethod);
+ return pm == null ? null : pm.field;
+ }
+
+ /**
+ * Returns the getter method associated with the property method.
+ * @param propertyMethod the identifying property method
+ * @return the getter or null if absent
+ */
+ public ExecutableElement getPropertyGetter(ExecutableElement propertyMethod) {
+ ensureInitialized();
+ PropertyMembers pm = propertyMap.get(propertyMethod);
+ return pm == null ? null : pm.getter;
+ }
+
+ /**
+ * Returns the setter method associated with the property method.
+ * @param propertyMethod the identifying property method
+ * @return the setter or null if absent
+ */
+ public ExecutableElement getPropertySetter(ExecutableElement propertyMethod) {
+ ensureInitialized();
+ PropertyMembers pm = propertyMap.get(propertyMethod);
+ return pm == null ? null : pm.setter;
+ }
+
+ boolean isUndocumentedEnclosure(TypeElement encl) {
+ return utils.isPackagePrivate(encl) && !utils.isLinkable(encl);
+ }
+
+ private void computeParents() {
+ for (TypeMirror intfType : te.getInterfaces()) {
+ TypeElement intfc = utils.asTypeElement(intfType);
+ if (intfc != null) {
+ VisibleMemberTable vmt = mcache.getVisibleMemberTable(intfc);
+ allSuperinterfaces.add(vmt);
+ parents.add(vmt);
+ allSuperinterfaces.addAll(vmt.getAllSuperinterfaces());
+ }
+ }
+
+ if (parent != null) {
+ VisibleMemberTable vmt = mcache.getVisibleMemberTable(parent);
+ allSuperclasses.add(vmt);
+ allSuperclasses.addAll(vmt.getAllSuperclasses());
+ // Add direct super interfaces of a super class, if any.
+ allSuperinterfaces.addAll(vmt.getAllSuperinterfaces());
+ parents.add(vmt);
+ }
+ }
+
+ private void computeVisibleMembers() {
+
+ // Note: these have some baggage, and are redundant,
+ // allow this to be GC'ed.
+ LocalMemberTable lmt = new LocalMemberTable();
+
+ for (Kind k : Kind.values()) {
+ computeLeafMembers(lmt, k);
+ computeVisibleMembers(lmt, k);
+ }
+ // All members have been computed, compute properties.
+ computeVisibleProperties(lmt);
+ }
+
+ private void computeLeafMembers(LocalMemberTable lmt, Kind kind) {
+ List<Element> list = new ArrayList<>();
+ if (isUndocumentedEnclosure(te)) {
+ list.addAll(lmt.getOrderedMembers(kind));
+ }
+ parents.forEach(pvmt -> {
+ list.addAll(pvmt.getExtraMembers(kind));
+ });
+ extraMembers.put(kind, Collections.unmodifiableList(list));
+ }
+
+ void computeVisibleMembers(LocalMemberTable lmt, Kind kind) {
+ switch (kind) {
+ case FIELDS: case INNER_CLASSES:
+ computeVisibleFieldsAndInnerClasses(lmt, kind);
+ return;
+
+ case METHODS:
+ computeVisibleMethods(lmt);
+ return;
+
+ // Defer properties related computations for later.
+ case PROPERTIES:
+ return;
+
+ default:
+ List<Element> list = lmt.getOrderedMembers(kind).stream()
+ .filter(this::mustDocument)
+ .collect(Collectors.toList());
+ visibleMembers.put(kind, Collections.unmodifiableList(list));
+ break;
+ }
+ }
+
+ private boolean mustDocument(Element e) {
+ return !utils.hasHiddenTag(e) && utils.shouldDocument(e);
+ }
+
+ private boolean allowInheritedMembers(Element e, Kind kind, LocalMemberTable lmt) {
+ return isInherited(e) && !isMemberHidden(e, kind, lmt);
+ }
+
+ private boolean isInherited(Element e) {
+ if (utils.isPrivate(e))
+ return false;
+
+ if (utils.isPackagePrivate(e))
+ // Allowed iff this type-element is in the same package as the element
+ return utils.containingPackage(e).equals(utils.containingPackage(te));
+
+ return true;
+ }
+
+ private boolean isMemberHidden(Element inheritedMember, Kind kind, LocalMemberTable lmt) {
+ Elements elementUtils = config.docEnv.getElementUtils();
+ switch(kind) {
+ default:
+ List<Element> list = lmt.getMembers(inheritedMember, kind);
+ if (list.isEmpty())
+ return false;
+ return elementUtils.hides(list.get(0), inheritedMember);
+ case METHODS: case CONSTRUCTORS: // Handled elsewhere.
+ throw new IllegalArgumentException("incorrect kind");
+ }
+ }
+
+ private void computeVisibleFieldsAndInnerClasses(LocalMemberTable lmt, Kind kind) {
+ Set<Element> result = new LinkedHashSet<>();
+ for (VisibleMemberTable pvmt : parents) {
+ result.addAll(pvmt.getExtraMembers(kind));
+ result.addAll(pvmt.getAllVisibleMembers(kind));
+ }
+
+ // Filter out members in the inherited list that are hidden
+ // by this type or should not be inherited at all.
+ List<Element> list = result.stream()
+ .filter(e -> allowInheritedMembers(e, kind, lmt)).collect(Collectors.toList());
+
+ // Prefix local results first
+ list.addAll(0, lmt.getOrderedMembers(kind));
+
+ // Filter out elements that should not be documented
+ list = list.stream()
+ .filter(this::mustDocument)
+ .collect(Collectors.toList());
+
+ visibleMembers.put(kind, Collections.unmodifiableList(list));
+ }
+
+ private void computeVisibleMethods(LocalMemberTable lmt) {
+ Set<Element> inheritedMethods = new LinkedHashSet<>();
+ Map<ExecutableElement, List<ExecutableElement>> overriddenByTable = new HashMap<>();
+ for (VisibleMemberTable pvmt : parents) {
+ // Merge the lineage overrides into local table
+ pvmt.overriddenMethodTable.entrySet().forEach(e -> {
+ OverridingMethodInfo p = e.getValue();
+ if (!p.simpleOverride) { // consider only real overrides
+ List<ExecutableElement> list = overriddenByTable.computeIfAbsent(p.overrider,
+ k -> new ArrayList<>());
+ list.add(e.getKey());
+ }
+ });
+ inheritedMethods.addAll(pvmt.getAllVisibleMembers(Kind.METHODS));
+
+ // Copy the extra members (if any) from the lineage.
+ if (!utils.shouldDocument(pvmt.te)) {
+ List<? extends Element> extraMethods = pvmt.getExtraMembers(Kind.METHODS);
+
+ if (lmt.getOrderedMembers(Kind.METHODS).isEmpty()) {
+ inheritedMethods.addAll(extraMethods);
+ continue;
+ }
+
+ // Check if an extra-method ought to percolate through.
+ for (Element extraMethod : extraMethods) {
+ boolean found = false;
+
+ List<Element> lmethods = lmt.getMembers(extraMethod, Kind.METHODS);
+ for (Element lmethod : lmethods) {
+ ExecutableElement method = (ExecutableElement)lmethod;
+ found = utils.elementUtils.overrides(method,
+ (ExecutableElement)extraMethod, te);
+ if (found)
+ break;
+ }
+ if (!found)
+ inheritedMethods.add(extraMethod);
+ }
+ }
+ }
+
+ // Filter out inherited methods that:
+ // a. cannot override (private instance members)
+ // b. are overridden and should not be visible in this type
+ // c. are hidden in the type being considered
+ // see allowInheritedMethods, which performs the above actions
+ List<Element> list = inheritedMethods.stream()
+ .filter(e -> allowInheritedMethods((ExecutableElement)e, overriddenByTable, lmt))
+ .collect(Collectors.toList());
+
+ // Filter out the local methods, that do not override or simply
+ // overrides a super method, or those methods that should not
+ // be visible.
+ Predicate<ExecutableElement> isVisible = m -> {
+ OverridingMethodInfo p = overriddenMethodTable.getOrDefault(m, null);
+ return p == null || !p.simpleOverride;
+ };
+ List<Element> mlist = lmt.getOrderedMembers(Kind.METHODS);
+ List<Element> llist = mlist.stream()
+ .map(m -> (ExecutableElement)m)
+ .filter(isVisible)
+ .collect(Collectors.toList());
+
+ // Merge the above lists, making sure the local methods precede
+ // the others
+ list.addAll(0, llist);
+
+ // Final filtration of elements
+ list = list.stream()
+ .filter(this::mustDocument)
+ .collect(Collectors.toList());
+
+ visibleMembers.put(Kind.METHODS, Collections.unmodifiableList(list));
+
+ // Copy over overridden tables from the lineage, and finish up.
+ for (VisibleMemberTable pvmt : parents) {
+ overriddenMethodTable.putAll(pvmt.overriddenMethodTable);
+ }
+ overriddenMethodTable = Collections.unmodifiableMap(overriddenMethodTable);
+ }
+
+ boolean isEnclosureInterface(Element e) {
+ TypeElement enclosing = utils.getEnclosingTypeElement(e);
+ return utils.isInterface(enclosing);
+ }
+
+ boolean allowInheritedMethods(ExecutableElement inheritedMethod,
+ Map<ExecutableElement, List<ExecutableElement>> inheritedOverriddenTable,
+ LocalMemberTable lmt) {
+
+ if (!isInherited(inheritedMethod))
+ return false;
+
+ final boolean haveStatic = utils.isStatic(inheritedMethod);
+ final boolean inInterface = isEnclosureInterface(inheritedMethod);
+
+ // Static methods in interfaces are never documented.
+ if (haveStatic && inInterface) {
+ return false;
+ }
+
+ // Multiple-Inheritance: remove the interface method that may have
+ // been overridden by another interface method in the hierarchy
+ //
+ // Note: The following approach is very simplistic and is compatible
+ // with old VMM. A future enhancement, may include a contention breaker,
+ // to correctly eliminate those methods that are merely definitions
+ // in favor of concrete overriding methods, for instance those that have
+ // API documentation and are not abstract OR default methods.
+ if (inInterface) {
+ List<ExecutableElement> list = inheritedOverriddenTable.get(inheritedMethod);
+ if (list != null) {
+ boolean found = list.stream()
+ .anyMatch(this::isEnclosureInterface);
+ if (found)
+ return false;
+ }
+ }
+
+ Elements elementUtils = config.docEnv.getElementUtils();
+
+ // Check the local methods in this type.
+ List<Element> lMethods = lmt.getMembers(inheritedMethod, Kind.METHODS);
+ for (Element lMethod : lMethods) {
+ // Ignore private methods or those methods marked with
+ // a "hidden" tag.
+ if (utils.isPrivate(lMethod))
+ continue;
+
+ // Remove methods that are "hidden", in JLS terms.
+ if (haveStatic && utils.isStatic(lMethod) &&
+ elementUtils.hides(lMethod, inheritedMethod)) {
+ return false;
+ }
+
+ // Check for overriding methods.
+ if (elementUtils.overrides((ExecutableElement)lMethod, inheritedMethod,
+ utils.getEnclosingTypeElement(lMethod))) {
+
+ // Disallow package-private super methods to leak in
+ TypeElement encl = utils.getEnclosingTypeElement(inheritedMethod);
+ if (isUndocumentedEnclosure(encl)) {
+ overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+ l -> new OverridingMethodInfo(inheritedMethod, false));
+ return false;
+ }
+ boolean simpleOverride = utils.isSimpleOverride((ExecutableElement)lMethod);
+ overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+ l -> new OverridingMethodInfo(inheritedMethod, simpleOverride));
+ return simpleOverride;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * This class encapsulates the details of local members, orderedMembers
+ * contains the members in the declaration order, additionally a
+ * HashMap is maintained for performance optimization to lookup
+ * members. As a future enhancement is perhaps to consolidate the ordering
+ * into a Map, capturing the insertion order, thereby eliminating an
+ * ordered list.
+ */
+ class LocalMemberTable {
+
+ // Maintains declaration order
+ private final Map<Kind, List<Element>> orderedMembers;
+
+ // Performance optimization
+ private final Map<Kind, Map<String, List<Element>>> memberMap;
+
+ LocalMemberTable() {
+ orderedMembers = new EnumMap<>(Kind.class);
+ memberMap = new EnumMap<>(Kind.class);
+
+ List<? extends Element> elements = te.getEnclosedElements();
+ for (Element e : elements) {
+ if (config.nodeprecated && utils.isDeprecated(e)) {
+ continue;
+ }
+ switch (e.getKind()) {
+ case CLASS:
+ case INTERFACE:
+ case ENUM:
+ case ANNOTATION_TYPE:
+ addMember(e, Kind.INNER_CLASSES);
+ break;
+ case FIELD:
+ addMember(e, Kind.FIELDS);
+ addMember(e, Kind.ANNOTATION_TYPE_FIELDS);
+ break;
+ case METHOD:
+ ExecutableElement ee = (ExecutableElement)e;
+ if (utils.isAnnotationType(te)) {
+ addMember(e, ee.getDefaultValue() == null
+ ? Kind.ANNOTATION_TYPE_MEMBER_REQUIRED
+ : Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
+ }
+ addMember(e, Kind.METHODS);
+ break;
+ case CONSTRUCTOR:
+ if (!utils.isEnum(te))
+ addMember(e, Kind.CONSTRUCTORS);
+ break;
+ case ENUM_CONSTANT:
+ addMember(e, Kind.ENUM_CONSTANTS);
+ break;
+ }
+ }
+
+ // Freeze the data structures
+ for (Kind kind : Kind.values()) {
+ orderedMembers.computeIfPresent(kind, (k, v) -> Collections.unmodifiableList(v));
+ orderedMembers.computeIfAbsent(kind, t -> Collections.emptyList());
+
+ memberMap.computeIfPresent(kind, (k, v) -> Collections.unmodifiableMap(v));
+ memberMap.computeIfAbsent(kind, t -> Collections.emptyMap());
+ }
+ }
+
+ String getMemberKey(Element e) {
+ return new SimpleElementVisitor9<String, Void>() {
+ @Override
+ public String visitExecutable(ExecutableElement e, Void aVoid) {
+ return e.getSimpleName() + ":" + e.getParameters().size();
+ }
+
+ @Override
+ protected String defaultAction(Element e, Void aVoid) {
+ return e.getSimpleName().toString();
+ }
+ }.visit(e);
+ }
+
+ void addMember(Element e, Kind kind) {
+ List<Element> list = orderedMembers.computeIfAbsent(kind, k -> new ArrayList<>());
+ list.add(e);
+
+ Map<String, List<Element>> map = memberMap.computeIfAbsent(kind, k -> new HashMap<>());
+ list = map.computeIfAbsent(getMemberKey(e), l -> new ArrayList<>());
+ list.add(e);
+ }
+
+ List<Element> getOrderedMembers(Kind kind) {
+ return orderedMembers.get(kind);
+ }
+
+ List<Element> getMembers(Element e, Kind kind) {
+ String key = getMemberKey(e);
+ return getMembers(key, kind);
+ }
+
+ List<Element> getMembers(String key, Kind kind) {
+ Map <String, List<Element>> map = memberMap.get(kind);
+ return map.getOrDefault(key, Collections.emptyList());
+ }
+
+ List<Element> getPropertyMethods(String methodName, int argcount) {
+ return getMembers(methodName + ":" + argcount, Kind.METHODS).stream()
+ .filter(m -> (utils.isPublic(m) || utils.isProtected(m)))
+ .collect(Collectors.toList());
+ }
+ }
+
+ /**
+ * The properties triad for a property method.
+ */
+ static class PropertyMembers {
+ final VariableElement field;
+ final ExecutableElement getter;
+ final ExecutableElement setter;
+
+ PropertyMembers(VariableElement field, ExecutableElement getter, ExecutableElement setter) {
+ this.field = field;
+ this.getter = getter;
+ this.setter = setter;
+ }
+
+ public String toString() {
+ return ("field: " + field + ", getter: " + getter + ", setter: " + setter);
+ }
+ }
+
+ /*
+ * JavaFX convention notes.
+ * A JavaFX property-method is a method, which ends with "Property" in
+ * its name, takes no parameters and typically returns a subtype of javafx.beans.
+ * ReadOnlyProperty, in the strictest sense. However, it may not always
+ * be possible for the doclet to have access to j.b.ReadOnlyProperty,
+ * for this reason the strict check is disabled via an undocumented flag.
+ *
+ * Note, a method should not be considered as a property-method,
+ * if it satisfied the previously stated conditions AND if the
+ * method begins with "set", "get" or "is".
+ *
+ * Supposing we have {@code BooleanProperty acmeProperty()}, then the
+ * property-name is "acme".
+ *
+ * Property field, one may or may not exist and could be private, and
+ * should match the property-method.
+ *
+ * A property-setter is a method starting with "set", and the
+ * first character of the upper-cased starting character of the property name, the
+ * method must take 1 argument and must return a <code>void</code>.
+ *
+ * Using the above example {@code void setAcme(Something s)} can be
+ * considered as a property-setter of the property "acme".
+ *
+ * A property-getter is a method starting with "get" and the first character
+ * upper-cased property-name, having no parameters. A method that does not take any
+ * parameters and starting with "is" and an upper-cased property-name,
+ * returning a primitive type boolean or BooleanProperty can also be
+ * considered as a getter, however there must be only one getter for every property.
+ *
+ * For example {@code Object getAcme()} is a property-getter, and
+ * {@code boolean isFoo()}
+ */
+ private void computeVisibleProperties(LocalMemberTable lmt) {
+ if (!config.javafx)
+ return;
+
+ PropertyUtils pUtils = config.propertyUtils;
+ List<ExecutableElement> list = visibleMembers.getOrDefault(Kind.METHODS, Collections.emptyList())
+ .stream()
+ .map(m -> (ExecutableElement)m)
+ .filter(pUtils::isPropertyMethod)
+ .collect(Collectors.toList());
+
+ visibleMembers.put(Kind.PROPERTIES, Collections.unmodifiableList(list));
+
+ List<ExecutableElement> propertyMethods = list.stream()
+ .filter(e -> utils.getEnclosingTypeElement(e) == te)
+ .collect(Collectors.toList());
+
+ // Compute additional properties related sundries.
+ for (ExecutableElement propertyMethod : propertyMethods) {
+ String baseName = pUtils.getBaseName(propertyMethod);
+ List<Element> flist = lmt.getMembers(baseName, Kind.FIELDS);
+ Element field = flist.isEmpty() ? null : flist.get(0);
+
+ Element getter = null, setter = null;
+ List<Element> found = lmt.getPropertyMethods(pUtils.getGetName(propertyMethod), 0);
+ if (!found.isEmpty()) {
+ // Getters have zero params, no overloads! pick the first.
+ getter = found.get(0);
+ }
+ if (getter == null) {
+ // Check if isProperty methods are present ?
+ found = lmt.getPropertyMethods(pUtils.getIsName(propertyMethod), 0);
+ if (!found.isEmpty()) {
+ String propertyTypeName = propertyMethod.getReturnType().toString();
+ // Check if the return type of property method matches an isProperty method.
+ if (pUtils.hasIsMethod(propertyMethod)) {
+ // Getters have zero params, no overloads!, pick the first.
+ getter = found.get(0);
+ }
+ }
+ }
+ found = lmt.getPropertyMethods(pUtils.getSetName(propertyMethod), 1);
+ if (found != null) {
+ for (Element e : found) {
+ if (pUtils.isValidSetterMethod((ExecutableElement)e)) {
+ setter = e;
+ break;
+ }
+ }
+ }
+
+ propertyMap.put(propertyMethod, new PropertyMembers((VariableElement)field,
+ (ExecutableElement)getter, (ExecutableElement)setter));
+
+ // Debugging purposes
+ // System.out.println("te: " + te + ": " + utils.getEnclosingTypeElement(propertyMethod) +
+ // ":" + propertyMethod.toString() + "->" + propertyMap.get(propertyMethod));
+ }
+ }
+
+
+ // Future cleanups
+
+ Map<ExecutableElement, SoftReference<ImplementedMethods>> implementMethodsFinders = new HashMap<>();
+
+ private ImplementedMethods getImplementedMethodsFinder(ExecutableElement method) {
+ SoftReference<ImplementedMethods> imf = implementMethodsFinders.get(method);
+ // IMF does not exist or referent was gc'ed away ?
+ if (imf == null || imf.get() == null) {
+ imf = new SoftReference<>(new ImplementedMethods(method));
+ implementMethodsFinders.put(method, imf);
+ }
+ return imf.get();
+ }
+
+ public List<ExecutableElement> getImplementedMethods(ExecutableElement method) {
+ ImplementedMethods imf = getImplementedMethodsFinder(method);
+ return imf.getImplementedMethods().stream()
+ .filter(m -> getsimplyOverriddenMethod(m) == null)
+ .collect(Collectors.toList());
+ }
+
+ public TypeMirror getImplementedMethodHolder(ExecutableElement method,
+ ExecutableElement implementedMethod) {
+ ImplementedMethods imf = getImplementedMethodsFinder(method);
+ return imf.getMethodHolder(implementedMethod);
+ }
+
+ private class ImplementedMethods {
+
+ private final Map<ExecutableElement, TypeMirror> interfaces = new HashMap<>();
+ private final List<ExecutableElement> methlist = new ArrayList<>();
+ private final TypeElement typeElement;
+ private final ExecutableElement method;
+
+ public ImplementedMethods(ExecutableElement method) {
+ this.method = method;
+ typeElement = utils.getEnclosingTypeElement(method);
+ Set<TypeMirror> intfacs = utils.getAllInterfaces(typeElement);
+ /*
+ * Search for the method in the list of interfaces. If found check if it is
+ * overridden by any other subinterface method which this class
+ * implements. If it is not overidden, add it in the method list.
+ * Do this recursively for all the extended interfaces for each interface
+ * from the list.
+ */
+ for (TypeMirror interfaceType : intfacs) {
+ ExecutableElement found = utils.findMethod(utils.asTypeElement(interfaceType), method);
+ if (found != null) {
+ removeOverriddenMethod(found);
+ if (!overridingMethodFound(found)) {
+ methlist.add(found);
+ interfaces.put(found, interfaceType);
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the list of interface methods which the method passed in the
+ * constructor is implementing. The search/build order is as follows:
+ * <pre>
+ * 1. Search in all the immediate interfaces which this method's class is
+ * implementing. Do it recursively for the superinterfaces as well.
+ * 2. Traverse all the superclasses and search recursively in the
+ * interfaces which those superclasses implement.
+ *</pre>
+ *
+ * @return SortedSet<ExecutableElement> of implemented methods.
+ */
+ List<ExecutableElement> getImplementedMethods() {
+ return methlist;
+ }
+
+ TypeMirror getMethodHolder(ExecutableElement ee) {
+ return interfaces.get(ee);
+ }
+
+ /**
+ * Search in the method list and check if it contains a method which
+ * is overridden by the method as parameter. If found, remove the
+ * overridden method from the method list.
+ *
+ * @param method Is this method overriding a method in the method list.
+ */
+ private void removeOverriddenMethod(ExecutableElement method) {
+ TypeElement overriddenClass = utils.overriddenClass(method);
+ if (overriddenClass != null) {
+ for (int i = 0; i < methlist.size(); i++) {
+ TypeElement te = utils.getEnclosingTypeElement(methlist.get(i));
+ if (te == overriddenClass || utils.isSubclassOf(overriddenClass, te)) {
+ methlist.remove(i); // remove overridden method
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Search in the already found methods' list and check if it contains
+ * a method which is overriding the method parameter or is the method
+ * parameter itself.
+ *
+ * @param method method to be searched
+ */
+ private boolean overridingMethodFound(ExecutableElement method) {
+ TypeElement containingClass = utils.getEnclosingTypeElement(method);
+ for (ExecutableElement listmethod : methlist) {
+ if (containingClass == utils.getEnclosingTypeElement(listmethod)) {
+ // it's the same method.
+ return true;
+ }
+ TypeElement te = utils.overriddenClass(listmethod);
+ if (te == null) {
+ continue;
+ }
+ if (te == containingClass || utils.isSubclassOf(te, containingClass)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * A simple container to encapsulate an overriding method
+ * and the type of override.
+ */
+ static class OverridingMethodInfo {
+ final ExecutableElement overrider;
+ final boolean simpleOverride;
+
+ public OverridingMethodInfo(ExecutableElement overrider, boolean simpleOverride) {
+ this.overrider = overrider;
+ this.simpleOverride = simpleOverride;
+ }
+ }
+}
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ColumnFormat.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ColumnFormat.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,7 @@
private String format;
private String header;
private Expression expression;
+ private boolean required = false;
private Object previousValue;
public ColumnFormat(int number) {
@@ -71,6 +72,9 @@
// the raw data.
format="0";
}
+
+ // Adjust required flag
+ expression.setRequired(required);
}
public void setWidth(int width) {
@@ -121,6 +125,14 @@
this.expression = e;
}
+ public void setRequired(boolean r) {
+ this.required = r;
+ }
+
+ public boolean isRequired() {
+ return this.required;
+ }
+
public void setPreviousValue(Object o) {
this.previousValue = o;
}
@@ -141,7 +153,8 @@
System.out.println(indent + indentAmount + "name=" + name
+ ";data=" + expression.toString() + ";header=" + header
+ ";format=" + format + ";width=" + width
- + ";scale=" + scale.toString() + ";align=" + align.toString());
+ + ";scale=" + scale.toString() + ";align=" + align.toString()
+ + ";required=" + required);
for (Iterator<OptionFormat> i = children.iterator(); i.hasNext(); /* empty */) {
OptionFormat of = i.next();
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/Expression.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/Expression.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
private Expression right;
private Operator operator;
private int ordinal = nextOrdinal++;
+ private boolean required = false;
Expression() {
if (debug) {
@@ -52,6 +53,7 @@
System.out.println("Setting left on " + ordinal + " to " + left);
}
this.left = left;
+ this.left.setRequired(required);
}
Expression getLeft() {
@@ -63,6 +65,7 @@
System.out.println("Setting right on " + ordinal + " to " + right);
}
this.right = right;
+ this.right.setRequired(required);
}
Expression getRight() {
@@ -80,6 +83,20 @@
return operator;
}
+ void setRequired(boolean r) {
+ this.required = r;
+ if (left != null) {
+ left.setRequired(required);
+ }
+ if (right != null) {
+ right.setRequired(required);
+ }
+ }
+
+ boolean isRequired() {
+ return required;
+ }
+
public String toString() {
StringBuilder b = new StringBuilder();
b.append('(');
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
System.err.println("Warning: Unresolved Symbol: "
+ id.getName() + " substituted NaN");
}
- return new Literal(Double.valueOf(Double.NaN));
+ return new Literal(e.isRequired() ? 0.0d : Double.NaN);
}
if (m.getVariability() == Variability.CONSTANT) {
if (debug) {
@@ -131,7 +131,9 @@
+ " (right = " + rn.doubleValue() + ")"
+ " to literal value " + result);
}
- return new Literal(Double.valueOf(result));
+ var literal = new Literal(result);
+ literal.setRequired(e.isRequired());
+ return literal;
}
}
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,13 +60,15 @@
private static final String FORMAT = "format";
private static final String ALIGN = "align";
private static final String SCALE = "scale";
+ private static final String REQUIRED = "required";
private static final String START = OPTION;
private static final Set<String> scaleKeyWords = Scale.keySet();
private static final Set<String> alignKeyWords = Alignment.keySet();
+ private static final Set<String> boolKeyWords = Set.of("true", "false");
private static String[] otherKeyWords = {
- OPTION, COLUMN, DATA, HEADER, WIDTH, FORMAT, ALIGN, SCALE
+ OPTION, COLUMN, DATA, HEADER, WIDTH, FORMAT, ALIGN, SCALE, REQUIRED
};
private static char[] infixOps = {
@@ -445,6 +447,16 @@
}
/**
+ * requiredstmt -> 'required' expression
+ */
+ private void requiredStmt(ColumnFormat cf) throws ParserException, IOException {
+ match(REQUIRED);
+ Token t = matchOne(boolKeyWords);
+ cf.setRequired(Boolean.parseBoolean(t.sval));
+ log(pdebug, "Parsed: required -> " + cf.isRequired());
+ }
+
+ /**
* statementlist -> optionalstmt statementlist
* optionalstmt -> 'data' expression
* 'header' quotedstring
@@ -452,6 +464,7 @@
* 'format' formatstring
* 'align' alignspec
* 'scale' scalespec
+ * 'required' boolean
*/
private void statementList(ColumnFormat cf)
throws ParserException, IOException {
@@ -472,6 +485,8 @@
alignStmt(cf);
} else if (lookahead.sval.compareTo(SCALE) == 0) {
scaleStmt(cf);
+ } else if (lookahead.sval.compareTo(REQUIRED) == 0) {
+ requiredStmt(cf);
} else {
return;
}
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options Thu Apr 26 17:59:02 2018 +0200
@@ -277,6 +277,7 @@
width 8
scale sec
format "0.000"
+ required true
}
}
@@ -537,6 +538,7 @@
width 8
scale sec
format "0.000"
+ required true
}
column {
header "^LGCC" /* Last GC Cause */
@@ -835,6 +837,7 @@
width 8
scale sec
format "0.000"
+ required true
}
}
@@ -917,6 +920,7 @@
width 8
scale sec
format "0.000"
+ required true
}
}
@@ -1015,6 +1019,7 @@
width 8
scale sec
format "0.000"
+ required true
}
}
@@ -1121,6 +1126,7 @@
width 8
scale sec
format "0.000"
+ required true
}
}
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Apr 26 17:59:02 2018 +0200
@@ -209,6 +209,7 @@
static final EditorSetting BUILT_IN_EDITOR = new EditorSetting(null, false);
private boolean debug = false;
+ private int debugFlags = 0;
public boolean testPrompt = false;
private Startup startup = null;
private boolean isCurrentlyRunningStartup = false;
@@ -261,25 +262,28 @@
MODULE_PATH("--module-path", true),
ADD_MODULES("--add-modules", false),
ADD_EXPORTS("--add-exports", false),
- TO_COMPILER("-C", false, false, true, false),
- TO_REMOTE_VM("-R", false, false, false, true),;
+ ENABLE_PREVIEW("--enable-preview", true),
+ SOURCE_RELEASE("-source", true, true, true, false, false), // virtual option, generated by --enable-preview
+ TO_COMPILER("-C", false, false, true, false, false),
+ TO_REMOTE_VM("-R", false, false, false, true, false),;
final String optionFlag;
final boolean onlyOne;
final boolean passFlag;
final boolean toCompiler;
final boolean toRemoteVm;
+ final boolean showOption;
private OptionKind(String optionFlag, boolean onlyOne) {
- this(optionFlag, onlyOne, true, true, true);
+ this(optionFlag, onlyOne, true, true, true, true);
}
- private OptionKind(String optionFlag, boolean onlyOne, boolean passFlag,
- boolean toCompiler, boolean toRemoteVm) {
+ private OptionKind(String optionFlag, boolean onlyOne, boolean passFlag, boolean toCompiler, boolean toRemoteVm, boolean showOption) {
this.optionFlag = optionFlag;
this.onlyOne = onlyOne;
this.passFlag = passFlag;
this.toCompiler = toCompiler;
this.toRemoteVm = toRemoteVm;
+ this.showOption= showOption;
}
}
@@ -314,8 +318,8 @@
return selectOptions(e -> e.getKey().toCompiler);
}
- String[] commonOptions() {
- return selectOptions(e -> e.getKey().passFlag);
+ String[] shownOptions() {
+ return selectOptions(e -> e.getKey().showOption);
}
void addAll(OptionKind kind, Collection<String> vals) {
@@ -348,6 +352,7 @@
private final OptionSpec<String> argModulePath = parser.accepts("module-path").withRequiredArg();
private final OptionSpec<String> argAddModules = parser.accepts("add-modules").withRequiredArg();
private final OptionSpec<String> argAddExports = parser.accepts("add-exports").withRequiredArg();
+ private final OptionSpecBuilder argEnablePreview = parser.accepts("enable-preview");
private final NonOptionArgumentSpec<String> argNonOptions = parser.nonOptions();
private Options opts = new Options();
@@ -449,6 +454,13 @@
.map(mp -> mp.contains("=") ? mp : mp + "=ALL-UNNAMED")
.collect(toList())
);
+ if (options.has(argEnablePreview)) {
+ opts.addAll(OptionKind.ENABLE_PREVIEW, List.of(
+ OptionKind.ENABLE_PREVIEW.optionFlag));
+ opts.addAll(OptionKind.SOURCE_RELEASE, List.of(
+ OptionKind.SOURCE_RELEASE.optionFlag,
+ System.getProperty("java.specification.version")));
+ }
if (failed) {
exitCode = 1;
@@ -1062,6 +1074,7 @@
builder.executionEngine(executionControlSpec);
}
state = builder.build();
+ InternalDebugControl.setDebugFlags(state, debugFlags);
shutdownSubscription = state.onShutdown((JShell deadState) -> {
if (deadState == state) {
hardmsg("jshell.msg.terminated");
@@ -2234,11 +2247,10 @@
InternalDebugControl.setDebugFlags(state, debug ? DBG_GEN : 0);
fluff("Debugging %s", debug ? "on" : "off");
} else {
- int flags = 0;
for (char ch : arg.toCharArray()) {
switch (ch) {
case '0':
- flags = 0;
+ debugFlags = 0;
debug = false;
fluff("Debugging off");
break;
@@ -2247,36 +2259,41 @@
fluff("REPL tool debugging on");
break;
case 'g':
- flags |= DBG_GEN;
+ debugFlags |= DBG_GEN;
fluff("General debugging on");
break;
case 'f':
- flags |= DBG_FMGR;
+ debugFlags |= DBG_FMGR;
fluff("File manager debugging on");
break;
case 'c':
- flags |= DBG_COMPA;
+ debugFlags |= DBG_COMPA;
fluff("Completion analysis debugging on");
break;
case 'd':
- flags |= DBG_DEP;
+ debugFlags |= DBG_DEP;
fluff("Dependency debugging on");
break;
case 'e':
- flags |= DBG_EVNT;
+ debugFlags |= DBG_EVNT;
fluff("Event debugging on");
break;
case 'w':
- flags |= DBG_WRAP;
+ debugFlags |= DBG_WRAP;
fluff("Wrap debugging on");
break;
+ case 'b':
+ cmdout.printf("RemoteVM Options: %s\nCompiler options: %s\n",
+ Arrays.toString(options.remoteVmOptions()),
+ Arrays.toString(options.compilerOptions()));
+ break;
default:
error("Unknown debugging option: %c", ch);
- fluff("Use: 0 r g f c d e w");
+ fluff("Use: 0 r g f c d e w b");
return false;
}
}
- InternalDebugControl.setDebugFlags(state, flags);
+ InternalDebugControl.setDebugFlags(state, debugFlags);
}
return true;
}
@@ -3112,7 +3129,7 @@
if (rawargs.trim().isEmpty()) {
// No arguments, display current settings (as option flags)
StringBuilder sb = new StringBuilder();
- for (String a : options.commonOptions()) {
+ for (String a : options.shownOptions()) {
sb.append(
a.startsWith("-")
? sb.length() > 0
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu Apr 26 17:59:02 2018 +0200
@@ -205,6 +205,7 @@
\ --add-modules <module>(,<module>)*\n\
\ Specify modules to resolve, or all modules on the\n\
\ module path if <module> is ALL-MODULE-PATHs\n\
+\ --enable-preview Allow code to depend on preview features of this release\n\
\ --startup <file> One run replacement for the startup definitions\n\
\ --no-startup Do not run the startup definitions\n\
\ --feedback <mode> Specify the initial feedback mode. The mode may be\n\
--- a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Thu Apr 26 17:59:02 2018 +0200
@@ -82,7 +82,6 @@
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.ParserFactory;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
@@ -91,6 +90,7 @@
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
import com.sun.tools.javac.util.Names;
+import static jdk.internal.jshell.debug.InternalDebugControl.DBG_FMGR;
import jdk.jshell.Snippet.Status;
/**
@@ -202,6 +202,7 @@
.map(in -> sh.sourceToFileObject(fileManager, in))
.collect(Collectors.toList());
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
+ state.debug(DBG_FMGR, "Task (%s %s) Options: %s\n", this, compilationUnits, allOptions);
return javacTaskPool.getTask(null, fileManager, diagnostics, allOptions, null,
compilationUnits, task -> {
JavacTaskImpl jti = (JavacTaskImpl) task;
--- a/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectorExtImpl.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectorExtImpl.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -28,7 +28,6 @@
import com.sun.management.GarbageCollectionNotificationInfo;
import com.sun.management.GarbageCollectorMXBean;
import com.sun.management.GcInfo;
-import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.util.List;
import javax.management.ListenerNotFoundException;
@@ -38,6 +37,7 @@
import javax.management.NotificationListener;
import javax.management.openmbean.CompositeData;
import sun.management.GarbageCollectorImpl;
+import sun.management.ManagementFactoryHelper;
/**
* Implementation class for the garbage collector.
@@ -59,12 +59,8 @@
private String[] poolNames = null;
private synchronized String[] getAllPoolNames() {
if (poolNames == null) {
- List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
- poolNames = new String[pools.size()];
- int i = 0;
- for (MemoryPoolMXBean m : pools) {
- poolNames[i++] = m.getName();
- }
+ // The order of all memory pool names is important as GcInfo is also created with same order.
+ poolNames = ManagementFactoryHelper.getAllMemoryPoolNames();
}
return poolNames;
}
--- a/src/jdk.pack/share/native/common-unpack/utils.h Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.pack/share/native/common-unpack/utils.h Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -33,16 +33,16 @@
#endif
// overflow management
-#define OVERFLOW ((uint)-1)
-#define PSIZE_MAX (OVERFLOW/2) /* normal size limit */
+#define POVERFLOW ((uint)-1)
+#define PSIZE_MAX (POVERFLOW/2) /* normal size limit */
inline size_t scale_size(size_t size, size_t scale) {
- return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
+ return (size > PSIZE_MAX / scale) ? POVERFLOW : size * scale;
}
inline size_t add_size(size_t size1, size_t size2) {
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX)
- ? OVERFLOW
+ ? POVERFLOW
: size1 + size2;
}
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Thu Apr 26 17:59:02 2018 +0200
@@ -2969,7 +2969,7 @@
}
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
- if (getMap().containsArrayKeys()) {
+ if (hasDefinedArrayProperties()) {
final String key = JSType.toString(longIndex);
final FindProperty find = findProperty(key, true);
if (find != null) {
@@ -2981,7 +2981,7 @@
}
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final int callSiteFlags) {
- if (getMap().containsArrayKeys()) {
+ if (hasDefinedArrayProperties()) {
final String key = JSType.toString(longIndex);
final FindProperty find = findProperty(key, true);
if (find != null) {
@@ -2993,7 +2993,7 @@
}
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final int callSiteFlags) {
- if (getMap().containsArrayKeys()) {
+ if (hasDefinedArrayProperties()) {
final String key = JSType.toString(longIndex);
final FindProperty find = findProperty(key, true);
if (find != null) {
@@ -3004,6 +3004,15 @@
return false;
}
+ private boolean hasDefinedArrayProperties() {
+ for (ScriptObject obj = this; obj != null; obj = obj.getProto()) {
+ if (obj.getMap().containsArrayKeys()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
//value agnostic
private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
if (longIndex >= oldLength) {
--- a/test/hotspot/gtest/memory/test_metaspace_allocation.cpp Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/gtest/memory/test_metaspace_allocation.cpp Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,7 @@
#include "memory/allocation.inline.hpp"
#include "memory/metaspace.hpp"
#include "runtime/mutex.hpp"
+#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
@@ -104,7 +105,12 @@
// Let every ~10th space be an anonymous one to test different allocation patterns.
const Metaspace::MetaspaceType msType = (os::random() % 100 < 10) ?
Metaspace::AnonymousMetaspaceType : Metaspace::StandardMetaspaceType;
- _spaces[i].space = new ClassLoaderMetaspace(_spaces[i].lock, msType);
+ {
+ // Pull lock during space creation, since this is what happens in the VM too
+ // (see ClassLoaderData::metaspace_non_null(), which we mimick here).
+ MutexLockerEx ml(_spaces[i].lock, Mutex::_no_safepoint_check_flag);
+ _spaces[i].space = new ClassLoaderMetaspace(_spaces[i].lock, msType);
+ }
_spaces[i].allocated = 0;
ASSERT_TRUE(_spaces[i].space != NULL);
}
@@ -171,6 +177,7 @@
} else {
size = os::random() % 64;
}
+ // Note: In contrast to space creation, no need to lock here. ClassLoaderMetaspace::allocate() will lock itself.
MetaWord* const p = _spaces[index].space->allocate(size, mdType);
if (p == NULL) {
// We very probably did hit the metaspace "until-gc" limit.
@@ -196,6 +203,7 @@
force_switch = true;
} else {
assert(_spaces[index].space != NULL && _spaces[index].allocated > 0, "Sanity");
+ // Note: do not lock here. In the "wild" (the VM), we do not so either (see ~ClassLoaderData()).
delete _spaces[index].space;
_spaces[index].space = NULL;
_spaces[index].allocated = 0;
--- a/test/hotspot/jtreg/ProblemList-graal.txt Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Thu Apr 26 17:59:02 2018 +0200
@@ -73,3 +73,14 @@
compiler/compilercontrol/directives/LogTest.java 8181753 generic-all
gc/g1/ihop/TestIHOPStatic.java 8199486 generic-all
+
+compiler/jvmci/compilerToVM/ReprofileTest.java 8201333 generic-all
+
+compiler/tiered/TieredLevelsTest.java 8202124 generic-all
+compiler/tiered/NonTieredLevelsTest.java 8202124 generic-all
+compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java 8202124 generic-all
+
+compiler/jvmci/meta/StableFieldTest.java CODETOOLS-7902162 generic-all
+compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/HotSpotConstantReflectionProviderTest.java CODETOOLS-7902162 generic-all
+compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderTest.java CODETOOLS-7902162 generic-all
+compiler/jvmci/events/JvmciShutdownEventTest.java CODETOOLS-7902162 generic-all
--- a/test/hotspot/jtreg/ProblemList.txt Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/ProblemList.txt Thu Apr 26 17:59:02 2018 +0200
@@ -80,11 +80,6 @@
serviceability/sa/TestRevPtrsForInvokeDynamic.java 8191270 generic-all
serviceability/sa/sadebugd/SADebugDTest.java 8163805 generic-all
-serviceability/tmtools/jstat/GcTest01.java 8199519 generic-all
-serviceability/tmtools/jstat/GcTest02.java 8199519 generic-all
-serviceability/tmtools/jstat/GcCauseTest01.java 8199519 generic-all
-serviceability/tmtools/jstat/GcCauseTest02.java 8199519 generic-all
-serviceability/tmtools/jstat/GcCauseTest03.java 8199519 generic-all
#############################################################################
@@ -97,12 +92,5 @@
# Java EE Module Removal
#
-runtime/appcds/jigsaw/classpathtests/ClassPathTests.java 8194310 generic-all Java EE Module Removal
-runtime/appcds/jigsaw/overridetests/OverrideTests.java 8194310 generic-all Java EE Module Removal
-runtime/SharedArchiveFile/BootAppendTests.java 8194310 generic-all Java EE Module Removal
-runtime/modules/PatchModule/PatchModuleClassList.java 8194310 generic-all Java EE Module Removal
compiler/c2/Test8007294.java 8194310 generic-all Java EE Module Removal
compiler/c2/Test6852078.java 8194310 generic-all Java EE Module Removal
-runtime/AppCDS/HelloExtTest.java 8194310 generic-all Java EE Module Removal
-runtime/AppCDS/javaldr/CheckAnonymousClass.java 8194310 generic-all Java EE Module Removal
-runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java 8194310 generic-all Java EE Module Removal
--- a/test/hotspot/jtreg/TEST.groups Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/TEST.groups Thu Apr 26 17:59:02 2018 +0200
@@ -145,7 +145,9 @@
ctw_2 = \
applications/ctw/modules/java_base.java \
- applications/ctw/modules/java_desktop.java
+ applications/ctw/modules/java_base_2.java \
+ applications/ctw/modules/java_desktop.java \
+ applications/ctw/modules/java_desktop_2.java
ctw_3 = \
applications/ctw/modules/javafx_graphics.java \
--- a/test/hotspot/jtreg/applications/ctw/modules/java_base.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_base.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @summary run CTW for all classes from java.base module
+ * @summary run CTW for some classes from java.base module
*
* @library /test/lib / /testlibrary/ctw/src
* @modules java.base/jdk.internal.jimage
@@ -34,5 +34,5 @@
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.base
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.base 0% 50%
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_base_2.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary run CTW for some classes from java.base module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.base
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.base 50% 100%
+ */
--- a/test/hotspot/jtreg/applications/ctw/modules/java_desktop.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_desktop.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @summary run CTW for all classes from java.desktop module
+ * @summary run CTW for some classes from java.desktop module
*
* @library /test/lib / /testlibrary/ctw/src
* @modules java.base/jdk.internal.jimage
@@ -34,5 +34,5 @@
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.desktop
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.desktop 0% 50%
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_desktop_2.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary run CTW for some classes from java.desktop module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.desktop
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.desktop 50% 100%
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/uncommontrap/FoldedIfNonDomMidIf.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/**
+ * @test
+ * @bug 8201368
+ * @summary IfNode::fold_compares() may lead to incorrect execution
+ *
+ * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation FoldedIfNonDomMidIf
+ *
+ */
+
+public class FoldedIfNonDomMidIf {
+ public static void main(String[] args) {
+ for (int i = 0; i < 20_000; i++) {
+ test_helper(0, 0);
+ test_helper(20, 0);
+ test(12);
+ }
+ if (test(14) != null) {
+ throw new RuntimeException("Incorrect code execution");
+ }
+ }
+
+ private static Object test(int i) {
+ return test_helper(i, 0x42);
+ }
+
+ static class A {
+
+ }
+
+ static final MyException myex = new MyException();
+
+ private static Object test_helper(int i, int j) {
+ Object res = null;
+ try {
+ if (i < 10) {
+ throw myex;
+ }
+
+ if (i == 14) {
+
+ }
+
+ if (i > 15) {
+ throw myex;
+ }
+ } catch (MyException e) {
+ if (j == 0x42) {
+ res = new A();
+ }
+ }
+ return res;
+ }
+
+ private static class MyException extends Exception {
+ }
+}
--- a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,7 +25,7 @@
* @test
* @requires vm.cds
* @bug 8005933
- * @summary Test that -Xshare:auto uses CDS when explicitly specified with -server.
+ * @summary -Xshare:auto is the default when -Xshare is not specified
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
@@ -45,34 +45,30 @@
output.shouldContain("Loading classes to share");
output.shouldHaveExitValue(0);
- pb = ProcessTools.createJavaProcessBuilder(
- "-server", "-XX:+UnlockDiagnosticVMOptions",
- "-XX:SharedArchiveFile=./XShareAuto.jsa", "-version");
- output = new OutputAnalyzer(pb.start());
- String outputString = output.getOutput();
- // We asked for server but it could be aliased to something else
- if (outputString.contains("Server VM") && !outputString.contains("emulated-client")) {
- // In server case we don't expect to see sharing flag
- output.shouldNotContain("sharing");
+
+ // We have 2 test cases:
+ String cases[] = {
+ "-Xshare:auto", // case [1]: -Xshare:auto is explicitly specified.
+ "-showversion" // case [2]: -Xshare:auto is not explicitly specified,
+ // but VM should still use it by default.
+ };
+
+ for (String x : cases) {
+ pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=./XShareAuto.jsa",
+ "-Xlog:cds",
+ x,
+ "-version");
+ output = new OutputAnalyzer(pb.start());
+ String outputString = output.getOutput();
+
+ if (!outputString.contains("Unable to map")) {
+ // sharing may not be enabled if XShareAuto.jsa cannot be mapped due to
+ // ASLR.
+ output.shouldContain("sharing");
+ }
output.shouldHaveExitValue(0);
}
- else {
- System.out.println("Skipping test - no Server VM available");
- return;
- }
-
- pb = ProcessTools.createJavaProcessBuilder(
- "-server", "-Xshare:auto", "-XX:+UnlockDiagnosticVMOptions",
- "-XX:SharedArchiveFile=./XShareAuto.jsa", "-Xlog:cds", "-version");
- output = new OutputAnalyzer(pb.start());
- try {
- output.shouldContain("sharing");
- } catch (RuntimeException e) {
- // if sharing failed due to ASLR or similar reasons,
- // check whether sharing was attempted at all (UseSharedSpaces)
- output.shouldContain("UseSharedSpaces:");
- output.shouldNotContain("Unable to map %s");
- }
- output.shouldHaveExitValue(0);
}
}
--- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -42,6 +42,8 @@
"-XX:SharedBaseAddress=8g",
"-Xmx128m",
"-Xlog:gc+metaspace=trace",
+ "-Xshare:off",
+ "-Xlog:cds=trace",
"-XX:+VerifyBeforeGC", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Narrow klass base: 0x0000000000000000");
@@ -54,6 +56,8 @@
"-XX:CompressedClassSpaceSize=3g",
"-Xmx128m",
"-Xlog:gc+metaspace=trace",
+ "-Xshare:off",
+ "-Xlog:cds=trace",
"-XX:+VerifyBeforeGC", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Narrow klass base: 0x0000000000000000, Narrow klass shift: 3");
@@ -66,6 +70,8 @@
"-Xmx30g",
"-XX:-UseAOT", // AOT explicitly set klass shift to 3.
"-Xlog:gc+metaspace=trace",
+ "-Xshare:off",
+ "-Xlog:cds=trace",
"-XX:+VerifyBeforeGC", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Narrow klass base: 0x0000000000000000");
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,11 +27,12 @@
* @summary Testing -Xbootclasspath/a support for CDS
* @requires vm.cds
* @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.base/jdk.internal.misc
* java.management
* jdk.internal.jvmstat/sun.jvmstat.monitor
* @compile javax/sound/sampled/MyClass.jasm
- * @compile org/omg/CORBA/Context.jasm
+ * @compile javax/annotation/processing/FilerException.jasm
* @compile nonjdk/myPackage/MyClass.java
* @build LoadClass
* @run main/othervm BootAppendTests
@@ -53,7 +54,8 @@
public class BootAppendTests {
private static final String APP_CLASS = "LoadClass";
private static final String BOOT_APPEND_MODULE_CLASS = "javax/sound/sampled/MyClass";
- private static final String BOOT_APPEND_DUPLICATE_MODULE_CLASS = "org/omg/CORBA/Context";
+ private static final String BOOT_APPEND_DUPLICATE_MODULE_CLASS =
+ "javax/annotation/processing/FilerException";
private static final String BOOT_APPEND_CLASS = "nonjdk/myPackage/MyClass";
private static final String BOOT_APPEND_MODULE_CLASS_NAME =
BOOT_APPEND_MODULE_CLASS.replace('/', '.');
@@ -141,21 +143,21 @@
// from -Xbootclasspath/a. Verify the behavior is the same at runtime
// when CDS is enabled.
//
- // The org.omg.CORBA.Context is a boot module class. The class on
- // the -Xbootclasspath/a path that has the same fully-qualified name
- // should not be loaded at runtime when CDS is enabled.
- // The one from the boot modules should be loaded instead.
+ // The javax/annotation/processing/FilerException is a platform module
+ // class. The class on the -Xbootclasspath/a path that has the same
+ // fully-qualified name should not be loaded at runtime when CDS is enabled.
+ // The one from the platform modules should be loaded instead.
public static void testBootAppendDuplicateModuleClass() throws Exception {
for (String mode : modes) {
CDSOptions opts = (new CDSOptions())
.setXShareMode(mode).setUseVersion(false)
- .addPrefix("--add-modules", "java.corba", "-showversion",
+ .addPrefix("-showversion",
"-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar)
.addSuffix("-Xlog:class+load=info",
APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
- CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context source: jrt:/java.corba");
+ CDSTestUtils.checkExec(out, opts, "[class,load] javax.annotation.processing.FilerException source: jrt:/java.compiler");
}
}
@@ -164,9 +166,9 @@
// using --limit-modules. Verify the behavior is the same at runtime when CDS
// is enabled.
//
- // The java.desktop module is excluded using --limit-modules at runtime,
- // javax.sound.sampled.MyClass is archived from -Xbootclasspath/a. It can be
- // loaded from the archive at runtime.
+ // The java.desktop module is excluded using --limit-modules at runtime
+ // CDS will be disabled with the --limit-modules option during runtime.
+ // javax.sound.sampled.MyClass will be loaded from the jar at runtime.
public static void testBootAppendExcludedModuleClass() throws Exception {
for (String mode : modes) {
CDSOptions opts = (new CDSOptions())
@@ -175,13 +177,18 @@
"--limit-modules=java.base", "-cp", appJar)
.addSuffix("-Xlog:class+load=info",
APP_CLASS, BOOT_APPEND_MODULE_CLASS_NAME);
-
- OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
- CDSTestUtils.checkExec(out, opts, "[class,load] javax.sound.sampled.MyClass");
-
- // When CDS is enabled, the shared class should be loaded from the archive.
+ CDSTestUtils.Result res = CDSTestUtils.run(opts);
+ String MATCH_PATTERN =
+ ".class.load. javax.sound.sampled.MyClass source:.*bootAppend.jar*";
if (mode.equals("on")) {
- CDSTestUtils.checkExec(out, opts, "[class,load] javax.sound.sampled.MyClass source: shared objects file");
+ res.assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(MATCH_PATTERN);
+ });
+ } else {
+ res.assertNormalExit(out -> {
+ out.shouldMatch(MATCH_PATTERN);
+ });
}
}
}
@@ -192,10 +199,12 @@
// --limit-modules. Verify the behavior is the same at runtime
// when CDS is enabled.
//
- // The org.omg.CORBA.Context is a boot module class. The class
- // on -Xbootclasspath/a that has the same fully-qualified name
- // as org.omg.CORBA.Context can be loaded at runtime when
- // java.corba is excluded.
+ // The javax.annotation.processing.FilerException is a platform module class.
+ // The class on -Xbootclasspath/a that has the same fully-qualified name
+ // as javax.annotation.processing.FilerException can be loaded at runtime when
+ // java.compiler is excluded.
+ // CDS is disabled during runtime if the --limit-modules option is
+ // specified.
public static void testBootAppendDuplicateExcludedModuleClass() throws Exception {
for (String mode : modes) {
CDSOptions opts = (new CDSOptions())
@@ -205,14 +214,18 @@
.addSuffix("-Xlog:class+load=info",
APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
- OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
- CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context");
- if (!CDSTestUtils.isUnableToMap(out)) {
- if (mode.equals("off")) {
- out.shouldMatch(".*\\[class,load\\] org.omg.CORBA.Context source:.*bootAppend.jar");
- } else {
- CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context source: shared objects file");
- }
+ CDSTestUtils.Result res = CDSTestUtils.run(opts);
+ String MATCH_PATTERN =
+ ".class.load. javax.annotation.processing.FilerException source:.*bootAppend.jar*";
+ if (mode.equals("on")) {
+ res.assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(MATCH_PATTERN);
+ });
+ } else {
+ res.assertNormalExit(out -> {
+ out.shouldMatch(MATCH_PATTERN);
+ });
}
}
}
@@ -222,8 +235,9 @@
// the same at runtime when CDS is enabled.
//
// The nonjdk.myPackage is not defined in named modules. The
- // archived nonjdk.myPackage.MyClass from -Xbootclasspath/a
- // can be loaded at runtime when CDS is enabled.
+ // nonjdk.myPackage.MyClass will be loaded from the jar in
+ // -Xbootclasspath/a since CDS will be disabled with the
+ // --limit-modules option.
public static void testBootAppendClass() throws Exception {
for (String mode : modes) {
CDSOptions opts = (new CDSOptions())
@@ -233,21 +247,26 @@
.addSuffix("-Xlog:class+load=info",
APP_CLASS, BOOT_APPEND_CLASS_NAME);
- OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
- CDSTestUtils.checkExec(out, opts, "[class,load] nonjdk.myPackage.MyClass");
-
- // If CDS is enabled, the nonjdk.myPackage.MyClass should be loaded
- // from the shared archive.
+ CDSTestUtils.Result res = CDSTestUtils.run(opts);
+ String MATCH_PATTERN =
+ ".class.load. nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
if (mode.equals("on")) {
- CDSTestUtils.checkExec(out, opts,
- "[class,load] nonjdk.myPackage.MyClass source: shared objects file");
+ res.assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(MATCH_PATTERN);
+ });
+ } else {
+ res.assertNormalExit(out -> {
+ out.shouldMatch(MATCH_PATTERN);
+ });
}
}
}
// Test #6: This is similar to Test #5. During runtime, an extra dir
// is appended to the bootclasspath. It should not invalidate
- // the shared archive.
+ // the shared archive. However, CDS will be disabled with the
+ // --limit-modules in the command line.
public static void testBootAppendExtraDir() throws Exception {
for (String mode : modes) {
CDSOptions opts = (new CDSOptions())
@@ -257,14 +276,18 @@
.addSuffix("-Xlog:class+load=info",
APP_CLASS, BOOT_APPEND_CLASS_NAME);
- OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
- CDSTestUtils.checkExec(out, opts, "[class,load] nonjdk.myPackage.MyClass");
-
- // If CDS is enabled, the nonjdk.myPackage.MyClass should be loaded
- // from the shared archive.
+ CDSTestUtils.Result res = CDSTestUtils.run(opts);
+ String MATCH_PATTERN =
+ ".class.load. nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
if (mode.equals("on")) {
- CDSTestUtils.checkExec(out, opts,
- "[class,load] nonjdk.myPackage.MyClass source: shared objects file");
+ res.assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0)
+ .shouldMatch(MATCH_PATTERN);
+ });
+ } else {
+ res.assertNormalExit(out -> {
+ out.shouldMatch(MATCH_PATTERN);
+ });
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/javax/annotation/processing/FilerException.jasm Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax/annotation/processing;
+
+public class FilerException
+ version 51:0
+{
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+
+public Method toString:"()Ljava/lang/String;"
+ stack 1 locals 1
+{
+ ldc String "hi";
+ areturn;
+}
+
+}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/org/omg/CORBA/Context.jasm Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package org/omg/CORBA;
-
-public class Context
- version 51:0
-{
-
-public Method "<init>":"()V"
- stack 1 locals 1
-{
- aload_0;
- invokespecial Method java/lang/Object."<init>":"()V";
- return;
-}
-
-
-public Method toString:"()Ljava/lang/String;"
- stack 1 locals 1
-{
- ldc String "hi";
- areturn;
-}
-
-}
--- a/test/hotspot/jtreg/runtime/appcds/HelloExtTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/HelloExtTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -51,8 +51,8 @@
String bootClassPath = "-Xbootclasspath/a:" + whiteBoxJar;
TestCommon.dump(appJar,
- TestCommon.list("org/omg/CORBA/ORB", "[Ljava/lang/Comparable;"),
- bootClassPath, "-verbose:class", "--add-modules", "java.corba");
+ TestCommon.list("javax/annotation/processing/FilerException", "[Ljava/lang/Comparable;"),
+ bootClassPath, "-verbose:class");
String prefix = ".class.load. ";
String class_pattern = ".*LambdaForm[$]MH[/][0123456789].*";
@@ -60,14 +60,14 @@
String pattern = prefix + class_pattern + suffix;
TestCommon.run("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
- "-cp", appJar, bootClassPath, "-verbose:class", "--add-modules", "java.corba", "HelloExt")
+ "-cp", appJar, bootClassPath, "-verbose:class", "HelloExt")
.assertNormalExit(output -> output.shouldNotMatch(pattern));
TestCommon.run("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
"-cp", appJar, bootClassPath, "-verbose:class",
"-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary",
- "--add-modules", "java.corba", "HelloExt")
+ "HelloExt")
.assertNormalExit(output -> output.shouldNotMatch(class_pattern));
}
}
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/AnonVmClassesDuringDump.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/javaldr/AnonVmClassesDuringDump.java Thu Apr 26 17:59:02 2018 +0200
@@ -61,8 +61,22 @@
// Set the following property to see logs for dynamically generated classes
// in STDOUT
"-Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true");
+
+ String prefix = ".class.load. ";
+ // class name pattern like the following:
+ // jdk.internal.loader.BuiltinClassLoader$$Lambda$1/1816757085
+ // java.lang.invoke.LambdaForm$MH/1585787493
+ String class_pattern = ".*Lambda([a-z0-9$]+)/([0-9]+).*";
+ String suffix = ".*source: shared objects file.*";
+ String pattern = prefix + class_pattern + suffix;
+ // during run time, anonymous classes shouldn't be loaded from the archive
TestCommon.run("-cp", appJar, "Hello")
- .assertNormalExit();
+ .assertNormalExit(output -> output.shouldNotMatch(pattern));
+
+ // inspect the archive and make sure no anonymous class is in there
+ TestCommon.run("-cp", appJar,
+ "-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary", "Hello")
+ .assertNormalExit(output -> output.shouldNotMatch(class_pattern));
}
}
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/CheckAnonymousClass.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/*
- * @test
- * @summary ensure no anonymous class is being dumped into the CDS archive
- * @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/appcds
- * @modules jdk.jartool/sun.tools.jar
- * @compile ../test-classes/Hello.java
- * @run main CheckAnonymousClass
- */
-
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class CheckAnonymousClass {
-
- public static void main(String[] args) throws Exception {
- JarBuilder.build("hello", "Hello");
-
- String appJar = TestCommon.getTestJar("hello.jar");
-
- TestCommon.dump(appJar, TestCommon.list("Hello", "org/omg/CORBA/ORB"),
- "--add-modules", "java.corba", "-Xlog:class+load=info");
-
- String prefix = ".class.load. ";
- // class name pattern like the following:
- // jdk.internal.loader.BuiltinClassLoader$$Lambda$1/1816757085
- // java.lang.invoke.LambdaForm$MH/1585787493
- String class_pattern = ".*Lambda([a-z0-9$]+)/([0-9]+).*";
- String suffix = ".*source: shared objects file.*";
- String pattern = prefix + class_pattern + suffix;
- // during run time, anonymous classes shouldn't be loaded from the archive
- TestCommon.run("-XX:+UnlockDiagnosticVMOptions",
- "-cp", appJar, "-Xlog:class+load=info", "--add-modules", "java.corba", "Hello")
- .assertNormalExit(output -> output.shouldNotMatch(pattern));
-
- // inspect the archive and make sure no anonymous class is in there
- TestCommon.run("-XX:+UnlockDiagnosticVMOptions",
- "-cp", appJar, "-Xlog:class+load=info", "-XX:+PrintSharedArchiveAndExit",
- "-XX:+PrintSharedDictionary", "--add-modules", "java.corba", "Hello")
- .assertNormalExit(output -> output.shouldNotMatch(class_pattern));
- }
-}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
* jdk.jartool/sun.tools.jar
* jdk.internal.jvmstat/sun.jvmstat.monitor
* @compile src/jdk/test/Main.java
- * @compile src/com/sun/tools/javac/Main2.jasm
+ * @compile src/com/sun/tools/javac/MyMain.jasm
* @compile src/sun/nio/cs/ext/MyClass.java
* @compile src/sun/nio/cs/ext1/MyClass.java
* @run main BootAppendTests
@@ -52,7 +52,7 @@
private static final Path CLASSES_DIR = Paths.get("classes");
private static final String MAIN_CLASS = "jdk.test.Main";
- private static final String APP_MODULE_CLASS = "com/sun/tools/javac/Main2";
+ private static final String APP_MODULE_CLASS = "com/sun/tools/javac/MyMain";
private static final String BOOT_APPEND_MODULE_CLASS = "sun/nio/cs/ext/MyClass";
private static final String BOOT_APPEND_CLASS = "sun/nio/cs/ext1/MyClass";
private static final String[] ARCHIVE_CLASSES =
@@ -239,7 +239,7 @@
MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT")
.assertSilentlyDisabledCDS(out -> {
out.shouldHaveExitValue(0)
- .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+ .shouldMatch(".class.load. com.sun.tools.javac.MyMain source:.*bootAppend.jar");
});
}
@@ -253,7 +253,7 @@
MAIN_CLASS, "Test #10", APP_MODULE_CLASS, "true", "BOOT")
.assertSilentlyDisabledCDS(out -> {
out.shouldHaveExitValue(0)
- .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+ .shouldMatch(".class.load. com.sun.tools.javac.MyMain source:.*bootAppend.jar");
});
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/ClassPathTests.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/ClassPathTests.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,12 +27,13 @@
* @requires vm.cds & !vm.graal.enabled
* @library ../..
* @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules jdk.jartool/sun.tools.jar
+ * @modules java.compiler
+ * java.base/jdk.internal.misc
+ * jdk.jartool/sun.tools.jar
* @compile src/jdk/test/Main.java
* @compile src/com/sun/tools/javac/Main.jasm
- * @compile src/com/sun/tools/javac/Main2.jasm
- * @compile src/javax/activation/UnsupportedDataTypeException2.jasm
+ * @compile src/com/sun/tools/javac/MyMain.jasm
+ * @compile ../../../SharedArchiveFile/javax/annotation/processing/FilerException.jasm
* @run main ClassPathTests
* @summary AppCDS tests for testing classpath/package conflicts
*/
@@ -73,8 +74,8 @@
// test classes to archive. These are both in UPGRADED_MODULES
private static final String JIMAGE_CLASS = "com/sun/tools/javac/Main";
- private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/Main2";
- private static final String PLATFORM_ARCHIVE_CLASS = "javax/activation/UnsupportedDataTypeException2";
+ private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/MyMain";
+ private static final String PLATFORM_ARCHIVE_CLASS = "javax/annotation/processing/FilerException";
private static final String[] ARCHIVE_CLASSES = {APP_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, JIMAGE_CLASS};
private static final int NUMBER_OF_TEST_CASES = 10;
@@ -111,15 +112,17 @@
// dump the archive with altnernate jdk.comiler and jdk.activation classes in the class list
OutputAnalyzer output1 = TestCommon.dump(appJar, TestCommon.list(ARCHIVE_CLASSES));
TestCommon.checkDump(output1);
- // Only a class that belongs to a module which is not defined by default
- // can be found. In this case the PLATFORM_ARCHIVE_CLASS belongs
- // to the java.activation which is not defined by default; it is the only
- // class can be found during dumping.
+ // The PLATFORM_ARCHIVE_CLASS belongs to the java.compiler
+ // module will be found from the module during dumping.
+ // The JIMAGE_CLASS will be found from the jdk.compiler module during
+ // dumping.
+ // The APP_ARCHIVE_CLASS, which belongs to a package within the
+ // jdk.compiler module, will not be found during dump time.
for (String archiveClass : ARCHIVE_CLASSES) {
- if (archiveClass.equals(PLATFORM_ARCHIVE_CLASS)) {
+ if (archiveClass.equals(APP_ARCHIVE_CLASS)) {
+ output1.shouldContain("Preload Warning: Cannot find " + archiveClass);
+ } else {
output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass);
- } else {
- output1.shouldContain("Preload Warning: Cannot find " + archiveClass);
}
}
@@ -146,82 +149,86 @@
CDSTestUtils.runWithArchiveAndCheck(opts);
}
- // For tests #3 and #4, we need to "--add-modules java.activation" since the
- // java.activation module won't be defined by default.
-
// #3: Archived classpath class in same package as jimage ext class. With AppCDS.
- // Should fail to load.
+ // The class should be loaded from the module.
public void testExtClassWithAppCDS() throws Exception {
OutputAnalyzer output = TestCommon.exec(
- appJar, "--add-modules", "java.activation", MAIN_CLASS,
- "Test #3", PLATFORM_ARCHIVE_CLASS, "false"); // last 3 args passed to test
+ appJar, MAIN_CLASS,
+ "Test #3", PLATFORM_ARCHIVE_CLASS, "true", "EXT"); // last 4 args passed to test
TestCommon.checkExec(output);
}
// #4: Archived classpath class in same package as jimage ext class. Without AppCDS.
- // Should fail to load.
+ // The class should be loaded from the module.
public void testExtClassWithoutAppCDS() throws Exception {
CDSOptions opts = (new CDSOptions())
- .addPrefix("-cp", appJar, "--add-modules", "java.activation")
+ .addPrefix("-cp", appJar)
.setArchiveName(testArchiveName)
- .addSuffix(MAIN_CLASS, "Test #4", PLATFORM_ARCHIVE_CLASS, "false");
+ .addSuffix(MAIN_CLASS, "Test #4", PLATFORM_ARCHIVE_CLASS, "true", "EXT");
CDSTestUtils.runWithArchiveAndCheck(opts);
}
// #5: Archived classpath class in same package as jimage app class. With AppCDS.
- // Should load because --limit-modules is used.
+ // Should load with CDS disabled because --limit-modules is used.
public void testAppClassWithLimitModsWithAppCDS() throws Exception {
- OutputAnalyzer output = TestCommon.exec(
- appJar,
- "--limit-modules", "java.base",
- MAIN_CLASS,
- "Test #5", APP_ARCHIVE_CLASS, "true"); // last 3 args passed to test
- TestCommon.checkExec(output);
+ TestCommon.run("-cp", appJar,
+ "--limit-modules", "java.base",
+ MAIN_CLASS,
+ "Test #5", APP_ARCHIVE_CLASS, "true") // last 3 args passed to test
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0);
+ });
}
// #6: Archived classpath class in same package as jimage app class. Without AppCDS.
- // Should load because --limit-modules is used.
+ // Should load with CDS disabled because --limit-modules is used.
public void testAppClassWithLimitModsWithoutAppCDS() throws Exception {
CDSOptions opts = (new CDSOptions())
.addPrefix("-cp", appJar, "--limit-modules", "java.base")
.setArchiveName(testArchiveName)
.addSuffix(MAIN_CLASS, "Test #6", APP_ARCHIVE_CLASS, "true");
-
- CDSTestUtils.runWithArchiveAndCheck(opts);
+ CDSTestUtils.run(opts)
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0);
+ });
}
// #7: Archived classpath class in same package as jimage ext class. With AppCDS.
- // Should load because --limit-modules is used.
+ // Should load with CDS disabled because --limit-modules is used.
public void testExtClassWithLimitModsWithAppCDS() throws Exception {
- OutputAnalyzer output = TestCommon.exec(
- appJar,
- "--limit-modules", "java.base",
- MAIN_CLASS,
- "Test #7", PLATFORM_ARCHIVE_CLASS, "true"); // last 3 args passed to test
- TestCommon.checkExec(output);
+ TestCommon.run("-cp", appJar,
+ "--limit-modules", "java.base",
+ MAIN_CLASS,
+ "Test #7", PLATFORM_ARCHIVE_CLASS, "true") // last 3 args passed to test
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0);
+ });
}
// #8: Archived classpath class in same package as jimage ext class. Without AppCDS.
- // Should load because --limit-modules is used.
+ // Should load with CDS disabled because --limit-modules is used.
public void testExtClassWithLimitModsWithoutAppCDS() throws Exception {
CDSOptions opts = (new CDSOptions())
.addPrefix("-cp", appJar, "--limit-modules", "java.base")
.setArchiveName(testArchiveName)
.addSuffix(MAIN_CLASS, "Test #8", PLATFORM_ARCHIVE_CLASS, "true");
-
- CDSTestUtils.runWithArchiveAndCheck(opts);
+ CDSTestUtils.run(opts)
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0);
+ });
}
// #9: Archived classpath class with same name as jimage app class. With AppCDS.
- // Should load because --limit-modules is used.
+ // Should load with CDS disabled because --limit-modules is used.
public void testReplacingJImageClassWithAppCDS() throws Exception {
- OutputAnalyzer output = TestCommon.exec(
- appJar,
- "--limit-modules", "java.base", "-XX:+TraceClassLoading",
- MAIN_CLASS,
- "Test #9", JIMAGE_CLASS, "true"); // last 3 args passed to test
- TestCommon.checkExec(output);
+ TestCommon.run("-cp", appJar,
+ "--limit-modules", "java.base",
+ MAIN_CLASS,
+ "Test #9", JIMAGE_CLASS, "true") // last 3 args passed to test
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0);
+ });
}
// #10: Archived classpath class with same name as jimage app class. Without AppCDS.
@@ -233,8 +240,9 @@
.addPrefix("-cp", appJar, "--limit-modules", "java.base")
.setArchiveName(testArchiveName)
.addSuffix(MAIN_CLASS, "Test #10", JIMAGE_CLASS, "true");
-
- CDSTestUtils.runWithArchiveAndCheck(opts);
+ CDSTestUtils.run(opts)
+ .assertSilentlyDisabledCDS(out -> {
+ out.shouldHaveExitValue(0);
+ });
}
-
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java Thu Apr 26 17:59:02 2018 +0200
@@ -27,11 +27,11 @@
* @summary Ensure that classes found in jimage takes precedence over classes found in -Xbootclasspath/a.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
- * @modules java.activation
+ * @modules java.compiler
* jdk.jartool/sun.tools.jar
* @compile ../../test-classes/DummyClassHelper.java
* @compile ../../test-classes/java/net/HttpCookie.jasm
- * @compile ../../test-classes/javax/activation/MimeType.jasm
+ * @compile ../../../SharedArchiveFile/javax/annotation/processing/FilerException.jasm
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main DummyClassesInBootClassPath
@@ -57,21 +57,20 @@
public static void main(String[] args) throws Exception {
String classNames[] = { "java/net/HttpCookie",
- "javax/activation/MimeType"};
+ "javax/annotation/processing/FilerException"};
JarBuilder.build("dummyClasses", classNames[0], classNames[1]);
String appJar = TestCommon.getTestJar("dummyClasses.jar");
OutputAnalyzer dumpOutput = TestCommon.dump(
- appJar, classNames, "-Xbootclasspath/a:" + appJar,
- "--add-modules", "java.activation");
+ appJar, classNames, "-Xbootclasspath/a:" + appJar);
List<String> argsList = new ArrayList<String>();
for (int i = 0; i < classNames.length; i++) {
argsList.add(classNames[i].replace('/', '.'));
}
String[] arguments = new String[argsList.size()];
arguments = argsList.toArray(arguments);
- Testcommon.run(
- "--add-modules", "java.activation", "-Xbootclasspath/a:" + appJar,
+ TestCommon.run(
+ "-Xbootclasspath/a:" + appJar,
"DummyClassHelper", arguments[0], arguments[1])
.assertNormalExit(output -> checkOutput(output, classNames));
@@ -80,14 +79,14 @@
String bootClassPath = "-Xbootclasspath/a:" + appJar +
File.pathSeparator + whiteBoxJar;
dumpOutput = TestCommon.dump(
- appJar, classNames, bootClassPath, "--add-modules", "java.activation");
+ appJar, classNames, bootClassPath);
argsList.add("testWithWhiteBox");
arguments = new String[argsList.size()];
arguments = argsList.toArray(arguments);
String[] opts = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
- "--add-modules", "java.activation", bootClassPath, "-Xlog:class+path=trace",
+ bootClassPath, "-Xlog:class+path=trace",
"DummyClassHelper", arguments[0], arguments[1], arguments[2]};
- Testcommon.run(opts)
+ TestCommon.run(opts)
.assertNormalExit(output -> checkOutput(output, classNames));
}
}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main2.jasm Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 com/sun/tools/javac;
-
-public class Main2
- version 51:0
-{
-
-public Method "<init>":"()V"
- stack 1 locals 1
-{
- aload_0;
- invokespecial Method java/lang/Object."<init>":"()V";
- return;
-}
-
-public Method toString:"()Ljava/lang/String;"
- stack 1 locals 1
-{
- ldc String "hi";
- areturn;
-}
-
-} // end class Main2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/MyMain.jasm Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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 com/sun/tools/javac;
+
+public class MyMain
+ version 51:0
+{
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+public Method toString:"()Ljava/lang/String;"
+ stack 1 locals 1
+{
+ ldc String "hi";
+ areturn;
+}
+
+} // end class Main2
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/javax/activation/UnsupportedDataTypeException2.jasm Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 javax/activation;
-
-public class UnsupportedDataTypeException2
- version 51:0
-{
-
-public Method "<init>":"()V"
- stack 1 locals 1
-{
- aload_0;
- invokespecial Method java/lang/Object."<init>":"()V";
- return;
-}
-
-public Method toString:"()Ljava/lang/String;"
- stack 1 locals 1
-{
- ldc String "hi";
- areturn;
-}
-
-} // end class UnsupportedDataTypeException2
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/jdk/test/Main.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/jdk/test/Main.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -96,10 +96,12 @@
}
// Make sure we got the right version of the class. toString() of an instance
// of the overridden version of the class should return "hi".
- String s = clazz.newInstance().toString();
- if (!s.equals("hi")) {
- throw new RuntimeException(testName + " FAILED: toString() returned \"" + s
- + "\" instead of \"hi\"" );
+ if (actualLoader == SYS_LOADER) {
+ String s = clazz.newInstance().toString();
+ if (!s.equals("hi")) {
+ throw new RuntimeException(testName + " FAILED: toString() returned \"" + s
+ + "\" instead of \"hi\"" );
+ }
}
System.out.println(testName + " PASSED: class loaded as expected.");
} else {
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/OverrideTests.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/OverrideTests.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -67,7 +67,7 @@
private static final Path MODS_DIR = Paths.get("mods");
// the module that is upgraded
- private static final String[] UPGRADED_MODULES = {"jdk.compiler", "java.activation"};
+ private static final String[] UPGRADED_MODULES = {"jdk.compiler", "java.net.http"};
private static final Path[] UPGRADEDMODS_DIR = {Paths.get("upgradedmod1"), Paths.get("upgradedmod2")};
// the test module
@@ -76,7 +76,7 @@
// test classes to archive. These are both in UPGRADED_MODULES
private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/Main";
- private static final String PLATFORM_ARCHIVE_CLASS = "javax/activation/UnsupportedDataTypeException";
+ private static final String PLATFORM_ARCHIVE_CLASS = "java/net/http/HttpTimeoutException";
private static final String[] ARCHIVE_CLASSES = {APP_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS};
private static String testArchiveName;
@@ -94,10 +94,10 @@
int i = 0;
for (String upgradedMod : UPGRADED_MODULES) {
compiled = CompilerUtils.compile(
- SRC_DIR.resolve(upgradedMod),
- UPGRADEDMODS_DIR[i].resolve(upgradedMod)
+ SRC_DIR.resolve(UPGRADED_MODULES[i]),
+ UPGRADEDMODS_DIR[i].resolve(UPGRADED_MODULES[i])
);
- Asserts.assertTrue(compiled, upgradedMod + " did not compile");
+ Asserts.assertTrue(compiled, UPGRADED_MODULES[i] + " did not compile");
i++;
}
@@ -110,22 +110,12 @@
);
Asserts.assertTrue(compiled, TEST_MODULE + " did not compile");
- // the java.activation module is not defined by default; --add-modules is required.
- // dumping without "--add-modules java.activation"
- // the class in the javax.activation package cannot be found
- OutputAnalyzer output1 = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES));
- TestCommon.checkDump(output1);
- output1.shouldContain(
- "Preload Warning: Cannot find javax/activation/UnsupportedDataTypeException");
-
- // dump the archive with jdk.comiler and java.activation classes in the class list
- // with "--add-modules java.activation"
- output1 = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES),
- "--add-modules", "java.activation");
- TestCommon.checkDump(output1);
+ // dump the archive with jdk.compiler and java.net.http classes in the class list
+ OutputAnalyzer output = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES));
+ TestCommon.checkDump(output);
// Make sure all the classes where successfully archived.
for (String archiveClass : ARCHIVE_CLASSES) {
- output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass);
+ output.shouldNotContain("Preload Warning: Cannot find " + archiveClass);
}
testArchiveName = TestCommon.getCurrentArchiveName();
@@ -147,11 +137,11 @@
/**
* PLATFORM Class Overriding Tests
*
- * Archive PLATFORM class javax.activation.UnsupportedDataTypeException from module jdk.activation.
- * -At run time, upgrade module jdk.activation using --upgrade-module-path.
- * Class.forname(UnsupportedDataTypeException) MUST NOT load the archived UnsupportedDataTypeException.
- * -At run time, module jdk.activation also exists in --module-path.
- * Class.forname(UnsupportedDataTypeException) MUST load the archived UnsupportedDataTypeException.
+ * Archive PLATFORM class java.net.http.HttpTimeoutException from module java.net.http.
+ * -At run time, upgrade module java.net.http using --upgrade-module-path.
+ * Class.forname(HttpTimeoutException) MUST NOT load the archived HttpTimeoutException.
+ * -At run time, module java.net.http also exists in --module-path.
+ * Class.forname(HttpTimeoutException) MUST load the archived HttpTimeoutException.
*/
public void testPlatformClassOverriding() throws Exception {
testClassOverriding(PLATFORM_ARCHIVE_CLASS, "platform");
@@ -173,25 +163,16 @@
prefix[0] = "-cp";
prefix[1] = "\"\"";
prefix[2] = "--add-modules";
- prefix[3] = "java.activation";
+ prefix[3] = "java.net.http";
// Run the test with --upgrade-module-path set to alternate location of archiveClass
// The alternate version of archiveClass SHOULD be found.
- output = TestCommon.execModule(
- prefix,
- UPGRADEDMODS_DIR[upgradeModIdx].toString(),
- MODS_DIR.toString(),
- mid,
- archiveClass, loaderName, "true"); // last 3 args passed to test
- if (isAppLoader) {
- try {
- output.shouldContain(expectedException);
- } catch (Exception e) {
- TestCommon.checkCommonExecExceptions(output, e);
- }
- } else {
- TestCommon.checkExec(output);
- }
+ TestCommon.runWithModules(prefix,
+ UPGRADEDMODS_DIR[upgradeModIdx].toString(),
+ MODS_DIR.toString(),
+ mid,
+ archiveClass, loaderName, "true") // last 3 args passed to test
+ .ifNoMappingFailure(out -> out.shouldContain(expectedException));
// Now run this same test again, but this time without AppCDS. Behavior should be the same.
CDSOptions opts = (new CDSOptions())
@@ -203,26 +184,21 @@
output = CDSTestUtils.runWithArchive(opts);
- if (isAppLoader) {
- try {
- output.shouldContain(expectedException);
- } catch (Exception e) {
- TestCommon.checkCommonExecExceptions(output, e);
- }
- } else {
- if (!CDSTestUtils.isUnableToMap(output))
- output.shouldHaveExitValue(0);
+ try {
+ output.shouldContain(expectedException);
+ } catch (Exception e) {
+ TestCommon.checkCommonExecExceptions(output, e);
}
// Run the test with -p set to alternate location of archiveClass.
// The alternate version of archiveClass SHOULD NOT be found.
- output = TestCommon.execModule(
+ TestCommon.runWithModules(
prefix,
null,
UPGRADEDMODS_DIR[upgradeModIdx].toString() + java.io.File.pathSeparator + MODS_DIR.toString(),
mid,
- archiveClass, loaderName, "false"); // last 3 args passed to test
- TestCommon.checkExec(output);
+ archiveClass, loaderName, "false") // last 3 args passed to test
+ .assertNormalExit();
// Now run this same test again, but this time without AppCDS. Behavior should be the same.
opts = (new CDSOptions())
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/javax/activation/UnsupportedDataTypeException.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 javax.activation;
-
-import java.io.IOException;
-
-public class UnsupportedDataTypeException extends IOException {
- public UnsupportedDataTypeException() {
- }
-
- public String toString() {
- return "hi";
- }
-}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/module-info.java Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- *
- */
-
-module java.activation {
- exports javax.activation;
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.net.http/java/net/http/HttpTimeoutException.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package java.net.http;
+
+public class HttpTimeoutException {
+ public String toString() {
+ return "hi";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.net.http/module-info.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.
+ *
+ */
+
+module java.net.http {
+ exports java.net.http;
+}
+
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/jdk/test/Main.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/jdk/test/Main.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -73,11 +73,15 @@
Class<?> clazz = Class.forName(className, true, loader);
// Make sure we got the expected defining ClassLoader
testLoader(clazz, loader);
- // Create an instance and see what toString() returns
- String s = clazz.newInstance().toString();
+
+ String s = null;
+ if (shouldOverride) {
+ // Create an instance and see what toString() returns
+ clazz.newInstance().toString();
+ }
// The overridden version of the class should return "hi". Make sure
// it does only if we are expecting to have loaded the overridden version.
- assertTrue(s.equals("hi") == shouldOverride);
+ assertTrue("hi".equals(s) == shouldOverride);
}
/**
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/module-info.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/module-info.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -24,5 +24,5 @@
module test {
requires jdk.compiler;
- requires java.activation;
+ requires java.compiler;
}
--- a/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExt.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExt.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -27,7 +27,7 @@
public class HelloExt {
public static void main(String[] args) throws Throwable {
- String className = "org.omg.CORBA.ORB";
+ String className = "javax.annotation.processing.FilerException";
Class cls = Class.forName(className);
ClassLoader loader = cls.getClassLoader();
--- a/test/hotspot/jtreg/runtime/appcds/test-classes/javax/activation/MimeType.jasm Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 javax/activation;
-
-public class MimeType
- version 51:0
-{
-
-public Method thisClassIsDummy:"()V"
- stack 0 locals 0
-{
- return;
-}
-
-} // end class MimeType
--- a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -40,7 +40,7 @@
public class PatchModuleClassList {
private static final String BOOT_CLASS = "javax/naming/spi/NamingManager";
- private static final String PLATFORM_CLASS = "javax/transaction/InvalidTransactionException";
+ private static final String PLATFORM_CLASS = "java/sql/ResultSet";
public static void main(String args[]) throws Throwable {
// Case 1. A class to be loaded by the boot class loader
@@ -68,7 +68,9 @@
"-XX:DumpLoadedClassList=" + classList,
"--patch-module=java.naming=" + moduleJar,
"PatchModuleMain", BOOT_CLASS.replace('/', '.'));
- new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
+ OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+ oa.shouldContain("I pass!");
+ oa.shouldHaveExitValue(0);
// check the generated classlist file
String content = new String(Files.readAllBytes(Paths.get(classList)));
@@ -78,30 +80,32 @@
// Case 2. A class to be loaded by the platform class loader
- // Create a class file in the module java.transaction. This class file
- // will be put in the javatransaction.jar file.
- source = "package javax.transaction; " +
- "public class InvalidTransactionException { " +
+ // Create a class file in the module java.sql. This class file
+ // will be put in the javasql.jar file.
+ source = "package java.sql; " +
+ "public class ResultSet { " +
" static { " +
- " System.out.println(\"I pass!\"); " +
+ " System.out.println(\"I pass too!\"); " +
" } " +
"}";
ClassFileInstaller.writeClassToDisk(PLATFORM_CLASS,
- InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "--patch-module=java.transaction"),
+ InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "--patch-module=java.sql"),
System.getProperty("test.classes"));
- // Build the jar file that will be used for the module "java.transaction".
- BasicJarBuilder.build("javatransaction", PLATFORM_CLASS);
- moduleJar = BasicJarBuilder.getTestJar("javatransaction.jar");
+ // Build the jar file that will be used for the module "java.sql".
+ BasicJarBuilder.build("javasql", PLATFORM_CLASS);
+ moduleJar = BasicJarBuilder.getTestJar("javasql.jar");
- classList = "javatransaction.list";
+ classList = "javasql.list";
pb = ProcessTools.createJavaProcessBuilder(
true,
"-XX:DumpLoadedClassList=" + classList,
- "--patch-module=java.naming=" + moduleJar,
+ "--patch-module=java.sql=" + moduleJar,
"PatchModuleMain", PLATFORM_CLASS.replace('/', '.'));
- new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
+ OutputAnalyzer oa2 = new OutputAnalyzer(pb.start());
+ oa2.shouldContain("I pass too!");
+ oa2.shouldHaveExitValue(0);
// check the generated classlist file
content = new String(Files.readAllBytes(Paths.get(classList)));
--- a/test/hotspot/jtreg/runtime/whitebox/WBStackSize.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/whitebox/WBStackSize.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -29,7 +29,8 @@
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xss512k WBStackSize
+ * @comment Must use the same stacksize for Java threads and compiler threads in case of thread recycling
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xss512k -XX:CompilerThreadStackSize=512 WBStackSize
*/
/*
@@ -82,9 +83,7 @@
}
public static void main(String[] args) {
- boolean isCompilerThread = Thread.currentThread().getName().indexOf(" CompilerThread") > 0;
- long configStackSize = isCompilerThread ? wb.getIntxVMFlag("CompilerThreadStackSize") * K
- : wb.getIntxVMFlag("ThreadStackSize") * K;
+ long configStackSize = wb.getIntxVMFlag("ThreadStackSize") * K;
System.out.println("ThreadStackSize VM option: " + configStackSize);
long stackProtectionSize = wb.getIntxVMFlag("StackShadowPages") * wb.getVMPageSize();
@@ -95,7 +94,7 @@
if (Math.abs(actualStackSize - configStackSize) > configStackSize * 0.1) {
throw new RuntimeException("getThreadFullStackSize value [" + actualStackSize
- + "] should be within 90%..110% of the value returned by HotSpotDiagnosticMXBean");
+ + "] should be within 90%..110% of ThreadStackSize value");
}
long remainingStackSize = wb.getThreadRemainingStackSize();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8174994
+ * @summary Test the clhsdb commands 'printmdo', 'printall' on a CDS enabled corefile.
+ * @requires vm.cds
+ * @requires os.family != "windows"
+ * @requires vm.flavor == "server"
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @run main/othervm/timeout=2400 -Xmx1g ClhsdbCDSCore
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.cds.CDSOptions;
+import java.io.IOException;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.Asserts;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import jdk.internal.misc.Unsafe;
+import java.util.Scanner;
+
+class CrashApp {
+ public static void main(String[] args) {
+ Unsafe.getUnsafe().putInt(0L, 0);
+ }
+}
+
+public class ClhsdbCDSCore {
+
+ private static final String TEST_CDS_CORE_FILE_NAME = "cds_core_file";
+ private static final String LOCATIONS_STRING = "location: ";
+ private static final String RUN_SHELL_NO_LIMIT = "ulimit -c unlimited && ";
+ private static final String SHARED_ARCHIVE_NAME = "ArchiveForClhsdbCDSCore.jsa";
+ private static final String CORE_PATTERN_FILE_NAME = "/proc/sys/kernel/core_pattern";
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Starting ClhsdbCDSCore test");
+ cleanup();
+
+ try {
+ CDSOptions opts = (new CDSOptions()).setArchiveName(SHARED_ARCHIVE_NAME);
+ CDSTestUtils.createArchiveAndCheck(opts);
+
+ String[] jArgs = {
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=" + SHARED_ARCHIVE_NAME,
+ "-XX:+CreateCoredumpOnCrash",
+ "-Xshare:auto",
+ "-XX:+ProfileInterpreter",
+ "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
+ CrashApp.class.getName()
+ };
+
+ OutputAnalyzer crashOut;
+ try {
+ List<String> options = new ArrayList<>();
+ options.addAll(Arrays.asList(jArgs));
+ crashOut =
+ ProcessTools.executeProcess(getTestJavaCommandlineWithPrefix(
+ RUN_SHELL_NO_LIMIT, options.toArray(new String[0])));
+ } catch (Throwable t) {
+ throw new Error("Can't execute the java cds process.", t);
+ }
+
+ System.out.println(crashOut.getOutput());
+ String crashOutputString = crashOut.getOutput();
+ String coreFileLocation = getCoreFileLocation(crashOutputString);
+ if (coreFileLocation == null) {
+ if (Platform.isOSX()) {
+ File coresDir = new File("/cores");
+ if (!coresDir.isDirectory() || !coresDir.canWrite()) {
+ throw new Error("cores is not a directory or does not have write permissions");
+ }
+ } else if (Platform.isLinux()) {
+ // Check if a crash report tool is installed.
+ File corePatternFile = new File(CORE_PATTERN_FILE_NAME);
+ Scanner scanner = new Scanner(corePatternFile);
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ line = line.trim();
+ System.out.println(line);
+ if (line.startsWith("|")) {
+ System.out.println(
+ "\nThis system uses a crash report tool ($cat /proc/sys/kernel/core_pattern).\n" +
+ "Core files might not be generated. Please reset /proc/sys/kernel/core_pattern\n" +
+ "to enable core generation. Skipping this test.");
+ cleanup();
+ return;
+ }
+ }
+ }
+ throw new Error("Couldn't find core file location in: '" + crashOutputString + "'");
+ }
+ try {
+ Asserts.assertGT(new File(coreFileLocation).length(), 0L, "Unexpected core size");
+ Files.move(Paths.get(coreFileLocation), Paths.get(TEST_CDS_CORE_FILE_NAME));
+ } catch (IOException ioe) {
+ throw new Error("Can't move core file: " + ioe, ioe);
+ }
+
+ ClhsdbLauncher test = new ClhsdbLauncher();
+
+ // Ensure that UseSharedSpaces is turned on.
+ List<String> cmds = List.of("flags UseSharedSpaces");
+
+ String useSharedSpacesOutput = test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds,
+ null, null);
+
+ if (useSharedSpacesOutput == null) {
+ // Output could be null due to attach permission issues.
+ System.out.println("Could not determine the UseSharedSpaces value - test skipped.");
+ cleanup();
+ return;
+ }
+
+ if (!useSharedSpacesOutput.contains("true")) {
+ // CDS archive is not mapped. Skip the rest of the test.
+ System.out.println("The CDS archive is not mapped - test skipped.");
+ cleanup();
+ return;
+ }
+
+ cmds = List.of("printmdo -a", "printall");
+
+ Map<String, List<String>> expStrMap = new HashMap<>();
+ Map<String, List<String>> unExpStrMap = new HashMap<>();
+ expStrMap.put("printmdo -a", List.of(
+ "CounterData",
+ "BranchData"));
+ unExpStrMap.put("printmdo -a", List.of(
+ "No suitable match for type of address"));
+ expStrMap.put("printall", List.of(
+ "aload_0",
+ "Constant Pool of",
+ "public static void main(java.lang.String[])",
+ "Bytecode",
+ "invokevirtual",
+ "checkcast",
+ "Exception Table",
+ "invokedynamic"));
+ unExpStrMap.put("printall", List.of(
+ "sun.jvm.hotspot.types.WrongTypeException",
+ "No suitable match for type of address"));
+ test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds, expStrMap, unExpStrMap);
+ } catch (Exception ex) {
+ throw new RuntimeException("Test ERROR " + ex, ex);
+ }
+ cleanup();
+ System.out.println("Test PASSED");
+ }
+
+ // lets search for a few possible locations using process output and return existing location
+ private static String getCoreFileLocation(String crashOutputString) {
+ Asserts.assertTrue(crashOutputString.contains(LOCATIONS_STRING),
+ "Output doesn't contain the location of core file.");
+ String stringWithLocation = Arrays.stream(crashOutputString.split("\\r?\\n"))
+ .filter(str -> str.contains(LOCATIONS_STRING))
+ .findFirst()
+ .get();
+ stringWithLocation = stringWithLocation.substring(stringWithLocation
+ .indexOf(LOCATIONS_STRING) + LOCATIONS_STRING.length());
+ String coreWithPid;
+ if (stringWithLocation.contains("or ")) {
+ Matcher m = Pattern.compile("or.* ([^ ]+[^\\)])\\)?").matcher(stringWithLocation);
+ if (!m.find()) {
+ throw new Error("Couldn't find path to core inside location string");
+ }
+ coreWithPid = m.group(1);
+ } else {
+ coreWithPid = stringWithLocation.trim();
+ }
+ if (new File(coreWithPid).exists()) {
+ return coreWithPid;
+ }
+ String justCore = Paths.get("core").toString();
+ if (new File(justCore).exists()) {
+ return justCore;
+ }
+ Path coreWithPidPath = Paths.get(coreWithPid);
+ String justFile = coreWithPidPath.getFileName().toString();
+ if (new File(justFile).exists()) {
+ return justFile;
+ }
+ Path parent = coreWithPidPath.getParent();
+ if (parent != null) {
+ String coreWithoutPid = parent.resolve("core").toString();
+ if (new File(coreWithoutPid).exists()) {
+ return coreWithoutPid;
+ }
+ }
+ return null;
+ }
+
+ private static String[] getTestJavaCommandlineWithPrefix(String prefix, String... args) {
+ try {
+ String cmd = ProcessTools.getCommandLine(ProcessTools.createJavaProcessBuilder(true, args));
+ return new String[]{"sh", "-c", prefix + cmd};
+ } catch (Throwable t) {
+ throw new Error("Can't create process builder: " + t, t);
+ }
+ }
+
+ private static void cleanup() {
+ remove(TEST_CDS_CORE_FILE_NAME);
+ remove(SHARED_ARCHIVE_NAME);
+ }
+
+ private static void remove(String item) {
+ File toDelete = new File(item);
+ toDelete.delete();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8174994
+ * @summary Test the clhsdb commands 'jstack', 'printall' with CDS enabled
+ * @requires vm.cds
+ * @library /test/lib
+ * @run main/othervm/timeout=2400 -Xmx1g ClhsdbCDSJstackPrintAll
+ */
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.cds.CDSOptions;
+import jdk.test.lib.apps.LingeredApp;
+
+public class ClhsdbCDSJstackPrintAll {
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Starting ClhsdbCDSJstackPrintAll test");
+ String sharedArchiveName = "ArchiveForClhsdbJstackPrintAll.jsa";
+ LingeredApp theApp = null;
+
+ try {
+ CDSOptions opts = (new CDSOptions()).setArchiveName(sharedArchiveName);
+ CDSTestUtils.createArchiveAndCheck(opts);
+
+ ClhsdbLauncher test = new ClhsdbLauncher();
+ List<String> vmArgs = Arrays.asList(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=" + sharedArchiveName,
+ "-Xshare:auto");
+ theApp = LingeredApp.startApp(vmArgs);
+ System.out.println("Started LingeredApp with pid " + theApp.getPid());
+
+ // Ensure that UseSharedSpaces is turned on.
+ List<String> cmds = List.of("flags UseSharedSpaces");
+
+ String useSharedSpacesOutput = test.run(theApp.getPid(), cmds,
+ null, null);
+
+ if (useSharedSpacesOutput == null) {
+ // Attach permission issues.
+ System.out.println("Could not determine the UseSharedSpaces value - test skipped.");
+ LingeredApp.stopApp(theApp);
+ return;
+ }
+
+ if (!useSharedSpacesOutput.contains("true")) {
+ // CDS archive is not mapped. Skip the rest of the test.
+ System.out.println("The CDS archive is not mapped - test skipped.");
+ LingeredApp.stopApp(theApp);
+ return;
+ }
+
+ cmds = List.of("jstack -v", "printall");
+
+ Map<String, List<String>> expStrMap = new HashMap<>();
+ Map<String, List<String>> unExpStrMap = new HashMap<>();
+ expStrMap.put("jstack -v", List.of(
+ "No deadlocks found",
+ "Common-Cleaner",
+ "Signal Dispatcher",
+ "Method*",
+ "LingeredApp.main"));
+ unExpStrMap.put("jstack -v", List.of(
+ "sun.jvm.hotspot.types.WrongTypeException",
+ "No suitable match for type of address"));
+ expStrMap.put("printall", List.of(
+ "aload_0",
+ "Constant Pool of",
+ "public static void main(java.lang.String[])",
+ "Bytecode",
+ "invokevirtual",
+ "checkcast",
+ "Exception Table",
+ "invokedynamic"));
+ unExpStrMap.put("printall", List.of(
+ "No suitable match for type of address"));
+ test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap);
+ } catch (Exception ex) {
+ throw new RuntimeException("Test ERROR " + ex, ex);
+ } finally {
+ LingeredApp.stopApp(theApp);
+ }
+ System.out.println("Test PASSED");
+ }
+}
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,7 @@
import jdk.test.lib.apps.LingeredApp;
import jdk.test.lib.Platform;
import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.process.OutputAnalyzer;
/**
@@ -68,6 +69,27 @@
/**
*
+ * Launches 'jhsdb clhsdb' and loads a core file.
+ * @param coreFileName - Name of the corefile to be loaded.
+ */
+ private void loadCore(String coreFileName)
+ throws IOException {
+
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+ launcher.addToolArg("clhsdb");
+ launcher.addToolArg("--core=" + coreFileName);
+ launcher.addToolArg("--exe=" + JDKToolFinder.getTestJDKTool("java"));
+ System.out.println("Starting clhsdb against corefile " + coreFileName +
+ " and exe " + JDKToolFinder.getTestJDKTool("java"));
+
+ ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+ processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+ toolProcess = processBuilder.start();
+ }
+
+ /**
+ *
* Runs 'jhsdb clhsdb' commands and checks for expected and unexpected strings.
* @param commands - clhsdb commands to execute.
* @param expectedStrMap - Map of expected strings per command which need to
@@ -159,4 +181,32 @@
attach(lingeredAppPid);
return runCmd(commands, expectedStrMap, unExpectedStrMap);
}
+
+ /**
+ *
+ * Launches 'jhsdb clhsdb', loads a core file, executes the commands,
+ * checks for expected and unexpected strings.
+ * @param coreFileName - Name of the core file to be debugged.
+ * @param commands - clhsdb commands to execute.
+ * @param expectedStrMap - Map of expected strings per command which need to
+ * be checked in the output of the command.
+ * @param unExpectedStrMap - Map of unexpected strings per command which should
+ * not be present in the output of the command.
+ * @return Output of the commands as a String.
+ */
+ public String runOnCore(String coreFileName,
+ List<String> commands,
+ Map<String, List<String>> expectedStrMap,
+ Map<String, List<String>> unExpectedStrMap)
+ throws IOException, InterruptedException {
+
+ if (!Platform.shouldSAAttach()) {
+ // Silently skip the test if we don't have enough permissions to attach
+ System.out.println("SA attach not expected to work - test skipped.");
+ return null;
+ }
+
+ loadCore(coreFileName);
+ return runCmd(commands, expectedStrMap, unExpectedStrMap);
+ }
}
--- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java Thu Apr 26 17:59:02 2018 +0200
@@ -74,10 +74,18 @@
assertThat(GCT >= 0, "Incorrect time value for GCT");
assertThat(GCT >= YGCT, "GCT < YGCT (total garbage collection time < young generation garbage collection time)");
- int CGC = getIntValue("CGC");
- float CGCT = getFloatValue("CGCT");
- assertThat(CGCT >= 0, "Incorrect time value for CGCT");
+ int CGC = 0;
+ float CGCT = 0.0f;
+ try {
+ CGC = getIntValue("CGC");
+ } catch (NumberFormatException e) {
+ if (!e.getMessage().equals("Unparseable number: \"-\"")) {
+ throw e;
+ }
+ }
if (CGC > 0) {
+ CGCT = getFloatValue("CGCT");
+ assertThat(CGCT >= 0, "Incorrect time value for CGCT");
assertThat(CGCT > 0, "Number of concurrent GC events is " + CGC + ", but CGCT is 0");
}
--- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java Thu Apr 26 17:59:02 2018 +0200
@@ -103,10 +103,18 @@
assertThat(GCT >= 0, "Incorrect time value for GCT");
assertThat(GCT >= YGCT, "GCT < YGCT (total garbage collection time < young generation garbage collection time)");
- int CGC = getIntValue("CGC");
- float CGCT = getFloatValue("CGCT");
- assertThat(CGCT >= 0, "Incorrect time value for CGCT");
+ int CGC = 0;
+ float CGCT = 0.0f;
+ try {
+ CGC = getIntValue("CGC");
+ } catch (NumberFormatException e) {
+ if (!e.getMessage().equals("Unparseable number: \"-\"")) {
+ throw e;
+ }
+ }
if (CGC > 0) {
+ CGCT = getFloatValue("CGCT");
+ assertThat(CGCT >= 0, "Incorrect time value for CGCT");
assertThat(CGCT > 0, "Number of concurrent GC events is " + CGC + ", but CGCT is 0");
}
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -52,11 +52,17 @@
private static final Predicate<String> IS_CLASS_LINE = Pattern.compile(
"^\\[\\d+\\]\\s*\\S+\\s*$").asPredicate();
+ private static final String USAGE = "Usage: CtwRunner <artifact to compile> [start[%] stop[%]]";
+
public static void main(String[] args) throws Exception {
- if (args.length != 1) {
- throw new Error("Usage: <artifact to compile>");
+ CtwRunner runner;
+ switch (args.length) {
+ case 1: runner = new CtwRunner(args[0]); break;
+ case 3: runner = new CtwRunner(args[0], args[1], args[2]); break;
+ default: throw new Error(USAGE);
}
- new CtwRunner(args[0]).run();
+
+ runner.run();
}
private final List<Throwable> errors;
@@ -64,7 +70,10 @@
private final Path targetPath;
private final String targetName;
- private CtwRunner(String target) {
+ private final int start, stop;
+ private final boolean isStartStopPercentage;
+
+ private CtwRunner(String target, String start, String stop) {
if (target.startsWith("modules")) {
targetPath = Paths
.get(Utils.TEST_JDK)
@@ -82,8 +91,29 @@
}
this.target = target;
errors = new ArrayList<>();
+
+ if (start.endsWith("%") && stop.endsWith("%")) {
+ int startPercentage = Integer.parseInt(start.substring(0, start.length() - 1));;
+ int stopPercentage = Integer.parseInt(stop.substring(0, stop.length() - 1));
+ if (startPercentage < 0 || startPercentage > 100 ||
+ stopPercentage < 0 || stopPercentage > 100) {
+ throw new Error(USAGE);
+ }
+ this.start = startPercentage;
+ this.stop = stopPercentage;
+ this.isStartStopPercentage = true;
+ } else if (!start.endsWith("%") && !stop.endsWith("%")) {
+ this.start = Integer.parseInt(start);
+ this.stop = Integer.parseInt(stop);
+ this.isStartStopPercentage = false;
+ } else {
+ throw new Error(USAGE);
+ }
}
+ private CtwRunner(String target) {
+ this(target, "0%", "100%");
+ }
private void run() {
startCtwforAllClasses();
@@ -105,15 +135,44 @@
}
}
+ private long start(long totalClassCount) {
+ if (isStartStopPercentage) {
+ return totalClassCount * start / 100;
+ } else if (start > totalClassCount) {
+ System.err.println("WARNING: start [" + start + "] > totalClassCount [" + totalClassCount + "]");
+ return totalClassCount;
+ } else {
+ return start;
+ }
+ }
+
+ private long stop(long totalClassCount) {
+ if (isStartStopPercentage) {
+ return totalClassCount * stop / 100;
+ } else if (stop > totalClassCount) {
+ System.err.println("WARNING: stop [" + start + "] > totalClassCount [" + totalClassCount + "]");
+ return totalClassCount;
+ } else {
+ return stop;
+ }
+ }
private void startCtwforAllClasses() {
- long classStart = 0L;
- long classCount = classCount();
+ long totalClassCount = classCount();
+
+ long classStart = start(totalClassCount);
+ long classStop = stop(totalClassCount);
+
+ long classCount = classStop - classStart;
Asserts.assertGreaterThan(classCount, 0L,
target + "(at " + targetPath + ") does not have any classes");
+
+ System.out.printf("Compiling %d classes (of %d total classes) starting at %d and ending at %d\n",
+ classCount, totalClassCount, classStart, classStop);
+
boolean done = false;
while (!done) {
- String[] cmd = cmd(classStart);
+ String[] cmd = cmd(classStart, classStop);
try {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
/* addTestVmAndJavaOptions = */ true,
@@ -138,11 +197,11 @@
Pair<String, Long> lastClass = getLastClass(out);
if (exitCode == 0) {
long lastIndex = lastClass == null ? -1 : lastClass.second;
- if (lastIndex != classCount) {
+ if (lastIndex != classStop) {
errors.add(new Error(phase + ": Unexpected zero exit code"
+ "before finishing all compilations."
+ " lastClass[" + lastIndex
- + "] != classCount[" + classCount + "]"));
+ + "] != classStop[" + classStop + "]"));
} else {
System.out.println("Executed CTW for all " + classCount
+ " classes in " + target + "(at " + targetPath + ")");
@@ -197,7 +256,7 @@
return null;
}
- private String[] cmd(long classStart) {
+ private String[] cmd(long classStart, long classStop) {
String phase = phaseName(classStart);
return new String[] {
"-Xbatch",
@@ -206,6 +265,7 @@
"-XX:+UnlockDiagnosticVMOptions",
// define phase start
"-DCompileTheWorldStartAt=" + classStart,
+ "-DCompileTheWorldStopAt=" + classStop,
// CTW library uses WhiteBox API
"-XX:+WhiteBoxAPI", "-Xbootclasspath/a:.",
// export jdk.internal packages used by CTW library
--- a/test/jdk/ProblemList.txt Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/ProblemList.txt Thu Apr 26 17:59:02 2018 +0200
@@ -510,8 +510,10 @@
# jdk_io
+java/io/FileOutputStream/AtomicAppend.java 8202062 macosx-all
java/io/pathNames/GeneralWin32.java 8180264 windows-all
+
############################################################################
# jdk_management
@@ -545,9 +547,11 @@
java/nio/Buffer/EqualsCompareTest.java 8193917 solaris-all
-java/nio/channels/Selector/Wakeup.java 6963118 windows-all
+java/nio/channels/DatagramChannel/ChangingAddress.java 7141822 macosx-all
-java/nio/channels/DatagramChannel/ChangingAddress.java 7141822 macosx-all
+java/nio/channels/FileChannel/AtomicAppend.java 8202062 macosx-all
+
+java/nio/channels/Selector/Wakeup.java 6963118 windows-all
java/nio/file/WatchService/Basic.java 7158947 solaris-all Solaris 11
java/nio/file/WatchService/MayFlies.java 7158947 solaris-all Solaris 11
@@ -586,6 +590,7 @@
javax/net/ssl/DTLS/PacketLossRetransmission.java 8169086 macosx-x64
javax/net/ssl/DTLS/RespondToRetransmit.java 8169086 macosx-x64
+javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64
sun/security/krb5/auto/UnboundSSL.java 8180265 windows-all
sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-all
@@ -738,6 +743,8 @@
com/sun/jdi/RedefineImplementor.sh 8004127 generic-all
+com/sun/jdi/JdbExprTest.sh 8185803 generic-all
+
com/sun/jdi/JdbMethodExitTest.sh 8171483 generic-all
com/sun/jdi/RepStep.java 8043571 generic-all
--- a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,8 @@
* @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false
* @modules java.management/sun.management
* jdk.management
- * @run main/othervm GarbageCollectionNotificationContentTest
- */
+ * @run main/othervm -Xms64m -Xmx64m GarbageCollectionNotificationContentTest
+ */
import java.util.*;
import java.lang.management.*;
@@ -97,7 +97,7 @@
System.gc();
// Allocation of many short living and small objects to trigger minor GC
Object data[] = new Object[32];
- for(int i = 0; i<100000000; i++) {
+ for(int i = 0; i<10000000; i++) {
data[i%32] = new int[8];
}
int wakeup = 0;
@@ -139,6 +139,8 @@
System.out.println("Usage for pool " + poolname);
System.out.println(" Before GC: " + busage);
System.out.println(" After GC: " + ausage);
+
+ checkMemoryUsage(poolname, busage, ausage);
}
// check if memory usage for all memory pools are returned
@@ -150,4 +152,13 @@
}
}
}
+
+ private static void checkMemoryUsage(String poolname, MemoryUsage busage, MemoryUsage ausage) throws Exception {
+ if (poolname.contains("Eden Space") && busage.getUsed() > 0) {
+ // Used size at Eden Space should be decreased or
+ if (busage.getUsed() <= ausage.getUsed()) {
+ throw new RuntimeException("Used size at Eden Space should be decreased.");
+ }
+ }
+ }
}
--- a/test/jdk/java/nio/channels/Selector/SelectAndCancel.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/java/nio/channels/Selector/SelectAndCancel.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,65 +23,61 @@
/* @test
* @bug 4729342
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * @run main SelectAndCancel
* @summary Check for CancelledKeyException when key cancelled during select
*/
-import java.nio.channels.*;
-import java.io.IOException;
-import java.net.*;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.util.concurrent.CountDownLatch;
public class SelectAndCancel {
- static SelectionKey sk;
+ static volatile SelectionKey sk;
+ static volatile Throwable ex;
/*
* CancelledKeyException is the failure symptom of 4729342
* NOTE: The failure is timing dependent and is not always
* seen immediately when the bug is present.
*/
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) throws Throwable {
final Selector selector = Selector.open();
- final ServerSocketChannel ssc =
- ServerSocketChannel.open().bind(new InetSocketAddress(0));
- final InetSocketAddress isa =
- new InetSocketAddress(InetAddress.getLocalHost(), ssc.socket().getLocalPort());
+ final ServerSocketChannel ssc = ServerSocketChannel.open().bind(
+ new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+ final InetSocketAddress isa = (InetSocketAddress)ssc.getLocalAddress();
+ final CountDownLatch signal = new CountDownLatch(1);
// Create and start a selector in a separate thread.
- new Thread(new Runnable() {
+ Thread t = new Thread(new Runnable() {
public void run() {
try {
ssc.configureBlocking(false);
sk = ssc.register(selector, SelectionKey.OP_ACCEPT);
+ signal.countDown();
selector.select();
- } catch (IOException e) {
- System.err.println("error in selecting thread");
- e.printStackTrace();
+ } catch (Throwable e) {
+ ex = e;
}
}
- }).start();
+ });
+ t.start();
- // Wait for above thread to get to select() before we call close.
- Thread.sleep(3000);
+ signal.await();
+ // Wait for above thread to get to select() before we call cancel.
+ Thread.sleep((long)(300 * jdk.test.lib.Utils.TIMEOUT_FACTOR));
- // Try to close. This should wakeup select.
- new Thread(new Runnable() {
- public void run() {
- try {
- SocketChannel sc = SocketChannel.open();
- sc.connect(isa);
- ssc.close();
- sk.cancel();
- sc.close();
- } catch (IOException e) {
- System.err.println("error in closing thread");
- System.err.println(e);
- }
- }
- }).start();
-
- // Wait for select() to be awakened, which should be done by close.
- Thread.sleep(3000);
-
- selector.wakeup();
+ // CancelledKeyException should not be thrown.
+ ssc.close();
+ sk.cancel();
selector.close();
+ t.join();
+ if (ex != null) {
+ throw ex;
+ }
}
}
--- a/test/jdk/java/security/AccessController/DoPrivAccompliceTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/java/security/AccessController/DoPrivAccompliceTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -104,7 +104,7 @@
ProcessTools.executeTestJava(commands)
.shouldHaveExitValue(0)
.shouldContain(userName)
- .stderrShouldBeEmpty();
+ .stderrShouldBeEmptyIgnoreVMWarnings();
createPolicyFile(jarFile2, policy);
System.out.println("Created policy for " + jarFile2);
--- a/test/jdk/sun/security/krb5/auto/Renewal.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/krb5/auto/Renewal.java Thu Apr 26 17:59:02 2018 +0200
@@ -161,8 +161,10 @@
return;
}
long change = (t.getTime() - System.currentTimeMillis()) / 1000;
- if (change > duration + 20 || change < duration - 20) {
- throw new Exception(t + " is not " + duration);
+ //accounting the delay factor in processing the instructions on host mc
+ if (change > duration + 40 || change < duration - 40) {
+ throw new Exception("Timestamp is " + t + ", actual difference "
+ + change + " is not " + duration);
}
}
}
--- a/test/jdk/sun/security/tools/keytool/KeyToolTest.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/tools/keytool/KeyToolTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,7 @@
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.security.cert.X509Certificate;
+import jdk.test.lib.util.FileUtils;
import sun.security.util.ObjectIdentifier;
public class KeyToolTest {
@@ -118,9 +119,10 @@
if (debug) {
System.err.println("Removing " + filename);
}
- new File(filename).delete();
- if (new File(filename).exists()) {
- throw new RuntimeException("Error deleting " + filename);
+ try{
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(filename));
+ }catch(IOException e) {
+ throw new RuntimeException("Error deleting " + filename, e);
}
}
--- a/test/jdk/sun/security/tools/keytool/autotest.sh Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/tools/keytool/autotest.sh Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,9 @@
# @test
# @summary (almost) all keytool behaviors
# @author Weijun Wang
-#
+# @library /test/lib
+# @build jdk.test.lib.util.FileUtils
+# @run shell/timeout=600 autotest.sh
# This test is only executed on several platforms
#
# set a few environment variables so that the shell-script can run stand-alone
@@ -92,6 +94,14 @@
exit 0;
;;
esac
+case "$OS" in
+ Windows_* | CYGWIN* )
+ PS=";"
+ ;;
+ * )
+ PS=":"
+ ;;
+esac
if [ "$LIBNAME" = "" ]; then
echo "Cannot find libsoftokn3.so"
@@ -103,8 +113,7 @@
EXTRAOPTS="--add-exports java.base/sun.security.tools.keytool=ALL-UNNAMED \
--add-exports java.base/sun.security.util=ALL-UNNAMED \
--add-exports java.base/sun.security.x509=ALL-UNNAMED"
-
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file \
+${COMPILEJAVA}${FS}bin${FS}javac -classpath ${TESTCLASSPATH} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file \
${TESTSRC}${FS}KeyToolTest.java || exit 10
NSS=${TESTSRC}${FS}..${FS}..${FS}pkcs11${FS}nss
@@ -116,8 +125,7 @@
chmod u+w key3.db
chmod u+w cert8.db
-
-echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -Dnss \
+echo | ${TESTJAVA}${FS}bin${FS}java -classpath .${PS}${TESTCLASSPATH} ${TESTVMOPTS} ${EXTRAOPTS} -Dnss \
-Dnss.lib=${LIBNAME} \
KeyToolTest
status=$?
--- a/test/jdk/sun/security/tools/keytool/standard.sh Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/tools/keytool/standard.sh Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 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
@@ -24,6 +24,8 @@
# @test
# @summary (almost) all keytool behaviors
# @author Weijun Wang
+# @library /test/lib
+# @build jdk.test.lib.util.FileUtils
# @run shell/timeout=600 standard.sh
# @key intermittent
@@ -57,14 +59,22 @@
exit 1;
;;
esac
+case "$OS" in
+ Windows_* | CYGWIN* )
+ PS=";"
+ ;;
+ * )
+ PS=":"
+ ;;
+esac
EXTRAOPTS="--add-exports java.base/sun.security.tools.keytool=ALL-UNNAMED \
--add-exports java.base/sun.security.util=ALL-UNNAMED \
--add-exports java.base/sun.security.x509=ALL-UNNAMED"
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10
+${COMPILEJAVA}${FS}bin${FS}javac -classpath ${TESTCLASSPATH} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10
-echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -Dfile KeyToolTest
+echo | ${TESTJAVA}${FS}bin${FS}java -classpath .${PS}${TESTCLASSPATH} ${TESTVMOPTS} ${EXTRAOPTS} -Dfile KeyToolTest
status=$?
exit $status
--- a/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*(-|[0-9]+)$/ {
datalines++;
}
--- a/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk Thu Apr 26 17:59:02 2018 +0200
@@ -14,7 +14,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/ {
datalines++;
}
--- a/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*(-|[0-9]+)$/ {
datalines++;
}
--- a/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk Thu Apr 26 17:59:02 2018 +0200
@@ -14,7 +14,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/ {
datalines++;
}
--- a/test/jdk/sun/tools/jstat/gcOldOutput1.awk Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcOldOutput1.awk Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/ {
datalines++;
}
--- a/test/jdk/sun/tools/jstat/gcOutput1.awk Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcOutput1.awk Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/ {
datalines++;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8025091
+ * @summary Tests the basic selection of FX related property methods, fields,
+ * setters and getters, by executing this test in the strict mode.
+ * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester propgen.PropGen
+ * @run main TestFxProperties
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class TestFxProperties extends JavadocTester {
+
+ public static void main(String... args) throws Exception {
+ TestFxProperties tester = new TestFxProperties();
+ if (!tester.sanity()) {
+ return;
+ }
+ tester.runTests();
+ }
+
+ // Check if FX modules are available.
+ boolean sanity() {
+ ClassLoader cl = this.getClass().getClassLoader();
+ try {
+ cl.loadClass("javafx.beans.Observable");
+ } catch (ClassNotFoundException cnfe) {
+ System.out.println("Note: javafx.beans.Observable: not found, test passes vacuously");
+ return false;
+ }
+ return true;
+ }
+
+ @Test
+ void test1() throws Exception {
+ Path srcdir = Paths.get("src-propgen");
+ Files.createDirectory(srcdir);
+ new propgen.PropGen(srcdir).run();
+ Path srcfile = Paths.get(srcdir.toString(), "Demo.java");
+
+ javadoc("-d", "out-propgen",
+ "--javafx",
+ srcfile.toString());
+ checkExit(Exit.OK);
+ checkOrder("Demo.html",
+ "PROPERTY SUMMARY",
+ "Property for fgp.",
+ "Property for fgsp.",
+ "Property for fp.",
+ "Property for fsp.",
+ "Property for gp.",
+ "Property for gsp.",
+ "Property for p.",
+ "Property for sp.",
+ "FIELD SUMMARY",
+ "Field for f.",
+ "Field for fg.",
+ "Field for fgp.",
+ "Field for fgs.",
+ "Field for fgsp.",
+ "Field for fp.",
+ "Field for fs.",
+ "Field for fsp.",
+ "CONSTRUCTOR SUMMARY"
+ );
+
+ checkOrder("Demo.html",
+ "METHOD SUMMARY",
+ "Getter for fg.",
+ "Getter for fgp.",
+ "Getter for fgs.",
+ "Getter for fgsp.",
+ "Getter for g.",
+ "Getter for gp.",
+ "Getter for gs.",
+ "Getter for gsp.",
+ "Setter for fgs.",
+ "Setter for fgsp.",
+ "Setter for fs.",
+ "Setter for fsp.",
+ "Setter for gs.",
+ "Setter for gsp.",
+ "Setter for s.",
+ "Setter for sp.",
+ "Methods inherited");
+ }
+}
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
/*
* @test
* @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363
- * 8167967 8172528 8175200 8178830 8182257 8186332 8182765
+ * 8167967 8172528 8175200 8178830 8182257 8186332 8182765 8025091
* @summary Test of the JavaFX doclet features.
* @author jvalenta
* @library ../lib
@@ -45,6 +45,7 @@
javadoc("-d", "out1",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"-package",
"pkg1");
checkExit(Exit.OK);
@@ -174,6 +175,7 @@
"-html4",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"-package",
"pkg1");
checkExit(Exit.OK);
@@ -200,6 +202,7 @@
javadoc("-d", "out2a",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"-package",
"pkg2");
checkExit(Exit.OK);
@@ -255,6 +258,7 @@
"-html4",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"-package",
"pkg2");
checkExit(Exit.OK);
@@ -390,6 +394,7 @@
void test4() {
javadoc("-d", "out4",
"--javafx",
+ "--disable-javafx-strict-checks",
"-Xdoclint:none",
"-sourcepath", testSrc,
"-package",
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/C.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/C.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -60,27 +60,28 @@
public final void setRate(double value) {}
- public final double getRate() {}
+ public final double getRate() { return 1.0d; }
- public final DoubleProperty rateProperty() {}
+ public final DoubleProperty rateProperty() { return null; }
private BooleanProperty paused;
public final void setPaused(boolean value) {}
- public final double isPaused() {}
+ public final double isPaused() { return 3.14d; }
/**
* Defines if paused. The second line.
* @defaultValue false
+ * @return foo
*/
- public final BooleanProperty pausedProperty() {}
+ public final BooleanProperty pausedProperty() { return null; }
class DoubleProperty {}
class BooleanProperty {}
- public final BooleanProperty setTestMethodProperty() {}
+ public final BooleanProperty setTestMethodProperty() { return null; }
private class Inner {
private BooleanProperty testMethodProperty() {}
@@ -94,8 +95,8 @@
public final void setRate(double value) {}
- public final double getRate() {}
+ public final double getRate() { return 3.14d; }
- public final DoubleProperty rateProperty() {}
+ public final DoubleProperty rateProperty() { return null; }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/propgen/PropGen.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package propgen;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class PropGen {
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) throws IOException {
+ new PropGen().run();
+ }
+
+ final PrintStream out;
+
+ final Path outFile;
+ final ByteArrayOutputStream baos;
+
+ PropGen() {
+ out = System.out;
+ outFile = null;
+ baos = null;
+ }
+
+ public PropGen(Path outDir) throws IOException {
+ outFile = Paths.get(outDir.toString(), "Demo.java");
+ baos = new ByteArrayOutputStream();
+ out = new PrintStream(baos);
+ }
+
+ enum Kind {
+ FIELD(1),
+ GETTER(2),
+ SETTER(4),
+ PROPERTY(8);
+ Kind(int bit) {
+ this.bit = bit;
+ }
+ int bit;
+ }
+
+ public void run() throws IOException {
+ out.println("import javafx.beans.property.Property;");
+ out.println("public class Demo {");
+ for (int i = 1; i < 16; i++) {
+ Set<Kind> set = EnumSet.noneOf(Kind.class);
+ for (Kind k : Kind.values()) {
+ if ((i & k.bit) == k.bit) {
+ set.add(k);
+ }
+ }
+ addItems(set);
+ }
+ out.println("}");
+ if (baos != null && outFile != null) {
+ Files.write(outFile, baos.toByteArray());
+ }
+ }
+
+ void addItems(Set<Kind> kinds) {
+ String name = kinds.stream()
+ .map(k -> k.name())
+ .map(s -> s.substring(0, 1))
+ .collect(Collectors.joining(""))
+ .toLowerCase();
+ if (kinds.contains(Kind.FIELD)) {
+ out.println(" /** Field for " + name + ". */");
+ out.println(" public Property " + name + ";");
+ }
+ if (kinds.contains(Kind.GETTER)) {
+ out.println(" /**");
+ out.println(" * Getter for " + name + ".");
+ out.println(" * @return a " + name);
+ out.println(" */");
+ out.println(" public Object " + mname("get", name) + "() { return null; }");
+ }
+ if (kinds.contains(Kind.SETTER)) {
+ out.println(" /**");
+ out.println(" * Setter for " + name + ".");
+ out.println(" * @param o a " + name);
+ out.println(" */");
+ out.println(" public void " + mname("set", name) + "(Object o) { }");
+ }
+ if (kinds.contains(Kind.PROPERTY)) {
+ out.println(" /**");
+ out.println(" * Property for " + name + ".");
+ out.println(" * @return the property for " + name);
+ out.println(" */");
+ out.println(" public Property " + name + "Property() { return null; }");
+ }
+ out.println();
+ }
+
+ String mname(String prefix, String base) {
+ return prefix + Character.toUpperCase(base.charAt(0)) + base.substring(1);
+ }
+
+}
--- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java Thu Apr 26 17:59:02 2018 +0200
@@ -181,6 +181,7 @@
javadoc("-d", "out-9",
"-linksource",
"-javafx",
+ "--disable-javafx-strict-checks",
"-sourcepath", testSrc,
"-package",
"linksource");
@@ -254,6 +255,7 @@
"-html4",
"-linksource",
"-javafx",
+ "--disable-javafx-strict-checks",
"-sourcepath", testSrc,
"-package",
"linksource");
--- a/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java Thu Apr 26 17:59:02 2018 +0200
@@ -578,6 +578,7 @@
void run() {
tester.javadoc("-d", "out-5",
"-javafx",
+ "--disable-javafx-strict-checks",
"-sourcepath", tester.testSrc(new File(".").getPath()),
"pkg5"
);
--- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java Thu Apr 26 17:59:02 2018 +0200
@@ -43,6 +43,7 @@
javadoc("-d", "out-bad-option",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"--override-methods=nonsense",
"pkg5");
@@ -55,6 +56,7 @@
javadoc("-d", "out-detail",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"--override-methods=detail",
"pkg5");
@@ -66,6 +68,7 @@
javadoc("-d", "out-summary",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"--override-methods=summary",
"pkg5");
--- a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java Thu Apr 26 17:59:02 2018 +0200
@@ -42,6 +42,7 @@
void testArrays() {
javadoc("-d", "out",
"-javafx",
+ "--disable-javafx-strict-checks",
"-sourcepath", testSrc,
"pkg");
checkExit(Exit.OK);
@@ -113,6 +114,7 @@
javadoc("-d", "out-html4",
"-html4",
"-javafx",
+ "--disable-javafx-strict-checks",
"-sourcepath", testSrc,
"pkg");
checkExit(Exit.OK);
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java Thu Apr 26 17:59:02 2018 +0200
@@ -285,6 +285,7 @@
javadoc("-d", "out-9",
"-sourcepath", testSrc,
"-javafx",
+ "--disable-javafx-strict-checks",
"-package",
"-use",
"pkgfx", "pkg3");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8025091 8198890
+ * @summary Verify the presence visible members in the case of
+ * member hiding and overridding.
+ * @library /tools/lib ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester toolbox.ToolBox builder.ClassBuilder
+ * @run main TestVisibleMembers
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import builder.AbstractBuilder;
+import builder.AbstractBuilder.Comment.Kind;
+import builder.ClassBuilder;
+import builder.ClassBuilder.*;
+
+import toolbox.ToolBox;
+import builder.ClassBuilder;
+
+public class TestVisibleMembers extends JavadocTester {
+
+ final ToolBox tb;
+ public static void main(String... args) throws Exception {
+ TestVisibleMembers tester = new TestVisibleMembers();
+ tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
+ }
+
+ TestVisibleMembers() {
+ tb = new ToolBox();
+ }
+
+ @Test
+ void testChronoDiamondLeafDetail(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitChronoDiamondLeaf(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=detail",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C.html", "METHOD SUMMARY",
+ "boolean", "equals", "java.lang.Object", "Method equals in p.C",
+ "C", "with", "java.lang.Object", "obj", "Method with in p.C",
+ "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.C",
+ "METHOD DETAIL");
+ checkOutput("p/C.html", false, "BImpl");
+
+ checkOrder("p/E.html", "METHOD SUMMARY",
+ "boolean", "equals", "java.lang.Object", "Method equals in p.E",
+ "C", "with", "java.lang.Object", "Method with in p.E",
+ "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.E",
+ "METHOD DETAIL");
+ checkOutput("p/E.html", false, "EImpl");
+ }
+
+ @Test
+ void testChronoDiamondLeafSummary(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitChronoDiamondLeaf(srcDir);
+
+ Path outDir = base.resolve("out-member");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=summary",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C.html", "METHOD SUMMARY",
+ "boolean", "equals", "java.lang.Object", "Method equals in p.C",
+ "C", "with", "java.lang.Object", "obj", "Method with in p.C",
+ "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.C",
+ "METHOD DETAIL");
+ checkOutput("p/C.html", false, "BImpl");
+
+ checkOrder("p/E.html", "METHOD SUMMARY",
+ "boolean", "equals", "java.lang.Object", "Method equals in p.E",
+ "C", "with", "java.lang.Object", "Method with in p.E",
+ "C", "with", "java.lang.Object", "long", "lvalue", "Method with in p.E",
+ "METHOD DETAIL");
+ checkOutput("p/E.html", false, "EImpl");
+ }
+
+ // see j.t.TemporalAdjuster
+ void emitChronoDiamondLeaf(Path srcDir) throws Exception {
+
+ // Interface A
+ MethodBuilder mbWith1 = MethodBuilder
+ .parse("default Object with(Object obj) {return null;}");
+ MethodBuilder mbWith2 = MethodBuilder
+ .parse("default Object with(Object obj, long lvalue) {return null;}");
+
+ new ClassBuilder(tb, "p.A")
+ .setModifiers("public", "interface")
+ .addMembers(mbWith1, mbWith2)
+ .write(srcDir);
+
+ // Interface B
+ mbWith1.setComments("{@inheritDoc}", "@param obj an object",
+ "@return something");
+
+ mbWith2.setComments("{@inheritDoc}", "@param obj an object",
+ "@param lvalue an lvalue", "@return something");
+
+ new ClassBuilder(tb, "p.B")
+ .setModifiers( "public", "interface")
+ .setExtends("A")
+ .addMembers(mbWith1, mbWith2)
+ .write(srcDir);
+
+ // Class BImpl
+ MethodBuilder mb31 = MethodBuilder.parse("C with(Object obj) {return null;}");
+ MethodBuilder mb32 = MethodBuilder.parse("C with(Object obj, Long lobj) {return null;}");
+ new ClassBuilder(tb, "p.BImpl<C extends B>")
+ .setModifiers( "abstract", "class")
+ .addImplements("B")
+ .addMembers(mb31, mb32)
+ .write(srcDir);
+
+ // Class C
+ new ClassBuilder(tb, "p.C")
+ .setModifiers("public", "class")
+ .setExtends("BImpl")
+ .addMembers(mbWith1.setReturn("C")
+ .setModifiers("public")
+ .setComments(AbstractBuilder.Comment.Kind.AUTO))
+ .addMembers(mbWith2.setReturn("C")
+ .setModifiers("public")
+ .setComments(AbstractBuilder.Comment.Kind.AUTO))
+ .addMembers(MethodBuilder.parse("public boolean equals(Object obj) { return false;}"))
+ .write(srcDir);
+
+ // Class EImpl
+ MethodBuilder mb41 = MethodBuilder.parse("C with(Object obj) {return null;}")
+ .setComments(Kind.NO_API_COMMENT);
+ MethodBuilder mb42 = MethodBuilder.parse("C with(Object obj, Long lobj) {return null;}");
+ new ClassBuilder(tb, "p.EImpl<C extends B>")
+ .setModifiers( "abstract", "class")
+ .addImplements("B")
+ .addMembers(mb41, mb42)
+ .write(srcDir);
+
+ // Class E
+ MethodBuilder mb51 = MethodBuilder.parse("public C with(Object obj) {return null;}");
+ MethodBuilder mb52 = MethodBuilder.parse("public C with(Object obj, long lvalue) {return null;}");
+ MethodBuilder mb53 = MethodBuilder.parse("public boolean equals(Object obj) { return false;}");
+ new ClassBuilder(tb, "p.E")
+ .setModifiers("public", "class")
+ .setExtends("EImpl")
+ .addMembers(mb51, mb52, mb53)
+ .write(srcDir);
+ }
+
+ @Test
+ void testNestedInterfaceDetail(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitNestedInterface(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=detail",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOutput("p/TA.html", false, "getTA");
+
+ checkOrder("p/Bar.html",
+ "doSomething()",
+ "getTA()");
+ }
+
+ @Test
+ void testNestedInterfaceSummary(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitNestedInterface(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=summary",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOutput("p/TA.html", false, "getTA");
+
+ checkOrder("p/Bar.html",
+ "doSomething()",
+ "getTA()");
+
+ checkOrder("p/Foo.html",
+ "Methods declared in",
+ "Bar.html",
+ "getTA");
+ }
+
+ // See jx.s.TransferHandler
+ void emitNestedInterface(Path srcDir) throws Exception {
+
+ ClassBuilder innerI = new ClassBuilder(tb, "HasTA")
+ .setModifiers("interface");
+ MethodBuilder interfaceMethod = MethodBuilder.parse("public TA getTa();")
+ .setComments(Kind.NO_API_COMMENT);
+ innerI.addMembers(interfaceMethod);
+
+ new ClassBuilder(tb, "p.TA")
+ .setModifiers("public", "class")
+ .addImplements("java.io.Serializable")
+ .addNestedClasses(innerI)
+ .write(srcDir);
+
+ new ClassBuilder(tb, "p.Foo")
+ .setModifiers("public", "class")
+ .setExtends("Bar")
+ .write(srcDir);
+
+ new ClassBuilder(tb, "p.Bar")
+ .setModifiers("public", "abstract", "class")
+ .addImplements("TA.HasTA")
+ .addMembers(
+ MethodBuilder.parse("public void doSomething(){}"),
+ MethodBuilder.parse("public TA getTA(){return null;}")
+ ).write(srcDir);
+ }
+
+ @Test
+ void testStreamsMissingLinksDetail(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitStreamsMissingLinks(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=detail",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C.html",
+ "METHOD DETAIL",
+ "public", "void", "method()",
+ "See Also:",
+ "sub()",
+ "sub1()");
+
+ checkOrder("p/ILong.html",
+ "METHOD DETAIL",
+ "default", "void", "forEach", "java.util.function.Consumer",
+ "java.lang.Long", "action",
+ "Do you see me", "#forEach(java.util.function.LongConsumer)",
+ "forEach(LongConsumer)",
+ "END OF CLASS DATA");
+
+ checkOrder("p/IImpl.html",
+ "METHOD DETAIL",
+ "Method sub in p.IImpl",
+ "Specified by:", "I.html", "II.html",
+ "END OF CLASS DATA");
+ }
+
+ @Test
+ void testStreamsMissingLinksSummary(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitStreamsMissingLinks(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=summary",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C.html",
+ "METHOD DETAIL",
+ "public", "void", "method()", "See Also:", "sub()", "I.sub1()",
+ "public", "void", "m", "Method in C. See", "I.length()"
+ );
+
+ checkOrder("p/ILong.html",
+ "METHOD DETAIL",
+ "default", "void", "forEach", "java.util.function.Consumer",
+ "java.lang.Long", "action",
+ "Do you see me", "QLong.html#forEach(Q)",
+ "QLong.forEach(LongConsumer)",
+ "END OF CLASS DATA");
+
+ checkOrder("p/IImpl.html",
+ "METHOD DETAIL",
+ "Method sub in p.IImpl",
+ "Specified by:", "I.html",
+ "END OF CLASS DATA");
+
+ checkUnique("p/IImpl.html", "Specified by:");
+ }
+
+ // see j.u.Spliterator
+ void emitStreamsMissingLinks(Path srcDir) throws Exception {
+ new ClassBuilder(tb, "p.I")
+ .setModifiers("public", "interface")
+ .addMembers(
+ MethodBuilder.parse("public I sub();"),
+ MethodBuilder.parse("public I sub1();"),
+ MethodBuilder.parse("public int length();")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.A")
+ .setModifiers("abstract", "class")
+ .addImplements("I")
+ .addMembers(
+ MethodBuilder.parse("public I sub() {}"),
+ MethodBuilder.parse("public I sub1() {}"),
+ MethodBuilder.parse("public int length(){return 0;}")
+ .setComments(Kind.NO_API_COMMENT),
+ MethodBuilder.parse("public void m(){}")
+ .setComments("Method in C. See {@link #length()}.")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.C")
+ .setModifiers("public", "class")
+ .setExtends("A").addImplements("I")
+ .addMembers(
+ MethodBuilder.parse("public I sub() {return null;}"),
+ MethodBuilder.parse("public I sub1() {return null;}")
+ .setComments(Kind.INHERIT_DOC),
+ MethodBuilder.parse(" public void method() {}")
+ .setComments("A method ", "@see #sub", "@see #sub1"),
+ MethodBuilder.parse("public int length(){return 1;}")
+ .setComments(Kind.NO_API_COMMENT)
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.II")
+ .setModifiers("public", "interface")
+ .setExtends("I")
+ .addMembers(
+ MethodBuilder.parse("default public I sub() {return null;}")
+ .setComments(Kind.NO_API_COMMENT)
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.IImpl")
+ .setModifiers("public", "class")
+ .addImplements("II")
+ .addMembers(
+ MethodBuilder.parse("public I sub() {return null;}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.QLong<P, Q, R>")
+ .setModifiers("public interface")
+ .addMembers(
+ MethodBuilder.parse("default void forEach(Q action) {}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.ILong")
+ .addImports("java.util.function.*")
+ .setModifiers("public", "interface")
+ .setExtends("QLong<Long, LongConsumer, Object>")
+ .addMembers(
+ MethodBuilder.parse("default void forEach(LongConsumer action) {}")
+ .setComments(Kind.NO_API_COMMENT),
+ MethodBuilder.parse("default void forEach(Consumer<Long> action) {}")
+ .setComments("Do you see me {@link #forEach(LongConsumer)} ?")
+ ).write(srcDir);
+ }
+
+ @Test
+ void testVisibleMemberTableDetail(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitVisibleMemberTable(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=detail",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C.html",
+ "METHOD DETAIL",
+ "public", "void", "m()", "Method m in p.B",
+ "public", "void", "n()", "Method n in p.A",
+ "public", "void", "o()", "Description copied from class:", ">A<", "Method o in p.A",
+ "public", "void", "p()", "Method p in p.B",
+ "END OF CLASS DATA");
+
+ checkOutput("p/C.html", false,
+ "Overrides",
+ "Methods declared in class p");
+
+ checkOrder("p/D.html",
+ "METHOD SUMMARY",
+ "void", "m", "Method m in p.D",
+ "void", "n", "Method n in p.D",
+ "void", "o", "Method o in p.D",
+ "void", "p", "Method p in p.D",
+ "CONSTRUCTOR DETAIL");
+
+ checkOutput("p/D.html", false,
+ "Description copied from class:",
+ "Overrides",
+ "Methods declared in class p");
+
+ checkOrder("p/E.html",
+ "METHOD SUMMARY",
+ "void", "m", "Method m in p.B",
+ "void", "n", "Method n in p.A",
+ "void", "o", "Method o in p.A",
+ "void", "p", "Method p in p.B",
+ "CONSTRUCTOR DETAIL");
+
+ checkOutput("p/E.html", false,
+ "Description copied from class:",
+ "Overrides",
+ "Methods declared in class p");
+ }
+
+ @Test
+ void testVisibleMemberTableSummary(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitVisibleMemberTable(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=summary",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C.html",
+ "METHOD SUMMARY",
+ "void", "m", "Method m in p.B",
+ "void", "n", "Method n in p.A",
+ "void", "o", "Method o in p.A",
+ "void", "p", "Method p in p.B",
+ "CONSTRUCTOR DETAIL");
+
+ checkOrder("p/C.html",
+ "METHOD DETAIL",
+ "public", "void", "m()", "Method m in p.B",
+ "public", "void", "n()", "Method n in p.A",
+ "public", "void", "o()", "Description copied from class:", ">A<", "Method o in p.A",
+ "public", "void", "p()", "Method p in p.B",
+ "END OF CLASS DATA");
+
+ checkOutput("p/C.html", false,
+ "Overrides",
+ "Methods declared in class p");
+
+ checkOrder("p/D.html",
+ "METHOD SUMMARY",
+ "void", "m", "Method m in p.D",
+ "void", "n", "Method n in p.D",
+ "void", "o", "Method o in p.D",
+ "void", "p", "Method p in p.D",
+ "CONSTRUCTOR DETAIL");
+
+ checkOutput("p/D.html", false,
+ "Description copied from class:",
+ "Overrides",
+ "Methods declared in class p");
+
+ checkOrder("p/E.html",
+ "METHOD SUMMARY",
+ "void", "m", "Method m in p.B",
+ "void", "n", "Method n in p.A",
+ "void", "o", "Method o in p.A",
+ "void", "p", "Method p in p.B",
+ "CONSTRUCTOR DETAIL");
+
+ checkOutput("p/E.html", false,
+ "Description copied from class:",
+ "Overrides",
+ "Methods declared in class p");
+
+ }
+
+ // emit a matrix of method variants
+ void emitVisibleMemberTable(Path srcDir) throws Exception {
+ new ClassBuilder(tb, "p.A")
+ .setModifiers("public", "class")
+ .addMembers(
+ MethodBuilder.parse("public void m() {}"),
+ MethodBuilder.parse("public void n() {}"),
+ MethodBuilder.parse("public void o() {}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.B")
+ .setModifiers("class")
+ .setExtends("A")
+ .addMembers(
+ MethodBuilder.parse("public void m() {}"),
+ MethodBuilder.parse("public void n() {}")
+ .setComments(Kind.INHERIT_DOC),
+ MethodBuilder.parse("public void o() {}")
+ .setComments(Kind.NO_API_COMMENT),
+ MethodBuilder.parse("public void p() {}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.C")
+ .setModifiers("public", "class")
+ .setExtends("B")
+ .addMembers(
+ MethodBuilder.parse("public void m() {}")
+ .setComments(Kind.NO_API_COMMENT),
+ MethodBuilder.parse("public void n() {}")
+ .setComments(Kind.NO_API_COMMENT),
+ MethodBuilder.parse("public void o() {}")
+ .setComments(Kind.NO_API_COMMENT),
+ MethodBuilder.parse("public void p() {}")
+ .setComments(Kind.NO_API_COMMENT)
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.D")
+ .setModifiers("public", "class")
+ .setExtends("B")
+ .addMembers(
+ MethodBuilder.parse("public void m() {}"),
+ MethodBuilder.parse("public void n() {}"),
+ MethodBuilder.parse("public void o() {}"),
+ MethodBuilder.parse("public void p() {}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.E")
+ .setModifiers("public", "class")
+ .setExtends("B")
+ .addMembers(
+ MethodBuilder.parse("public void m() {}")
+ .setComments(Kind.INHERIT_DOC),
+ MethodBuilder.parse("public void n() {}")
+ .setComments(Kind.INHERIT_DOC),
+ MethodBuilder.parse("public void o() {}")
+ .setComments(Kind.INHERIT_DOC),
+ MethodBuilder.parse("public void p() {}")
+ .setComments(Kind.INHERIT_DOC)
+ ).write(srcDir);
+ }
+
+ @Test
+ void testHiddenMembersDetail(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitHiddenMembers(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=detail",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C1.html",
+ "FIELD SUMMARY",
+ "Fields inherited from interface", "I1", "field2",
+ "Fields inherited from interface", "I2", "field2",
+ "Fields inherited from interface", "I3", "field",
+ "METHOD SUMMARY",
+ "Methods inherited from interface", "I1", "method2",
+ "Methods inherited from interface", "I2", "method2",
+ "Methods inherited from interface", "I3", "method",
+ "CONSTRUCTOR DETAIL");
+
+ checkOrder("p/C2.html",
+ "FIELD SUMMARY",
+ "int", "field", "Field field in p.C2",
+ "Fields inherited from interface", "I1", "field2",
+ "Fields inherited from interface", "I2", "field2",
+ "METHOD SUMMARY",
+ "void", "method", "Method method in p.C2",
+ "void", "method2", "Method method2 in p.C2");
+
+ }
+
+ @Test
+ void testHiddenMembersSummary(Path base) throws Exception {
+ Path srcDir = base.resolve("src");
+ emitHiddenMembers(srcDir);
+
+ Path outDir = base.resolve("out");
+ javadoc("-d", outDir.toString(),
+ "-html5",
+ "--override-methods=summary",
+ "-sourcepath", srcDir.toString(),
+ "p");
+ checkExit(Exit.OK);
+
+ checkOrder("p/C1.html",
+ "Field Summary",
+ "Fields declared in interface", "I1", "field2",
+ "Fields declared in interface", "I2", "field2",
+ "Fields declared in interface", "I3", "field",
+ "Method Summary",
+ "Methods declared in interface", "I1", "method2",
+ "Methods declared in interface", "I2", "method2",
+ "Methods declared in interface", "I3", "method",
+ "Constructor Detail");
+
+ checkOrder("p/C2.html",
+ "Field Summary",
+ "int", "field", "Field field in p.C2",
+ "Fields declared in interface", "I1", "field2",
+ "Fields declared in interface", "I2", "field2",
+ "Method Summary",
+ "void", "method", "Method method in p.C2",
+ "void", "method2", "Method method2 in p.C2");
+
+ }
+
+ void emitHiddenMembers(Path srcDir) throws Exception {
+ new ClassBuilder(tb, "p.I1")
+ .setModifiers("public", "interface")
+ .addMembers(
+ FieldBuilder.parse("public static int field = 3;"),
+ FieldBuilder.parse("public static int field2 = 3;"),
+ MethodBuilder.parse("public void method();"),
+ MethodBuilder.parse("public void method2();"),
+ MethodBuilder.parse("public static void staticMethod() {}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.I2")
+ .setModifiers("public", "interface")
+ .addMembers(
+ FieldBuilder.parse("public static int field = 3;"),
+ FieldBuilder.parse("public static int field2 = 3;"),
+ MethodBuilder.parse("public void method();"),
+ MethodBuilder.parse("public void method2();"),
+ MethodBuilder.parse("public static void staticMethod() {}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.I3")
+ .setExtends("I1, I2")
+ .setModifiers("public", "interface")
+ .addMembers(
+ FieldBuilder.parse("public static int field = 3;"),
+ MethodBuilder.parse("public void method();"),
+ MethodBuilder.parse("public static void staticMethod() {}")
+ ).write(srcDir);
+
+ new ClassBuilder(tb, "p.C1")
+ .setModifiers("public", "abstract", "class")
+ .addImplements("I3")
+ .write(srcDir);
+
+ new ClassBuilder(tb, "p.C2")
+ .setExtends("C1")
+ .setModifiers("public", "abstract", "class")
+ .addMembers(
+ FieldBuilder.parse("public int field;"),
+ MethodBuilder.parse("public void method(){}"),
+ MethodBuilder.parse("public void method2(){}")
+ ).write(srcDir);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/jshell/ToolEnablePreviewTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8199193
+ * @summary Tests for the --enable-preview option
+ * @run testng ToolEnablePreviewTest
+ */
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+public class ToolEnablePreviewTest extends ReplToolTesting {
+
+ @Test
+ public void testOptionDebug() {
+ String release = System.getProperty("java.specification.version");
+ test(
+ (a) -> assertCommand(a, "/debug b",
+ "RemoteVM Options: []\n"
+ + "Compiler options: []"),
+ (a) -> assertCommand(a, "/env --enable-preview",
+ "| Setting new options and restoring state."),
+ (a) -> assertCommandCheckOutput(a, "/debug b", s -> {
+ assertTrue(s.contains("RemoteVM Options: [--enable-preview]"));
+ assertTrue(s.contains("Compiler options: [-source, " + release + ", --enable-preview]")
+ || s.contains("Compiler options: [--enable-preview, -source, " + release + "]"),
+ "\nExpected -- " + "Compiler options: [-source, " + release + ", --enable-preview]"
+ + "\nOr -- " + "Compiler options: [--enable-preview, -source, " + release + "]"
+ + "\nBut got -- " + s);
+ })
+ );
+ }
+
+ @Test
+ public void testCommandLineFlag() {
+ String release = System.getProperty("java.specification.version");
+ test(new String[] {"--enable-preview"},
+ (a) -> assertCommandCheckOutput(a, "/debug b", s -> {
+ assertTrue(s.contains("RemoteVM Options: [--enable-preview]"));
+ assertTrue(s.contains("Compiler options: [-source, " + release + ", --enable-preview]")
+ || s.contains("Compiler options: [--enable-preview, -source, " + release + "]"),
+ "\nExpected -- " + "Compiler options: [-source, " + release + ", --enable-preview]"
+ + "\nOr -- " + "Compiler options: [--enable-preview, -source, " + release + "]"
+ + "\nBut got -- " + s);
+ })
+ );
+ }
+
+ @Test
+ public void testCompilerTestFlagEnv() {
+ test(new String[] {"-C", "-XDforcePreview"},
+ (a) -> assertCommandOutputContains(a, "Function<Integer,Integer> f = i -> i + i",
+ "Error", "preview feature"),
+ (a) -> assertCommand(a, "/env --enable-preview",
+ "| Setting new options and restoring state."),
+ (a) -> assertCommandOutputContains(a, "Function<Integer,Integer> f = i -> i + i",
+ "f ==> ")
+ );
+ }
+
+ @Test
+ public void testCompilerTestFlag() {
+ test(new String[] {"-C", "-XDforcePreview", "--enable-preview"},
+ (a) -> assertCommandOutputContains(a, "Function<Integer,Integer> f = i -> i + i",
+ "f ==> "),
+ (a) -> assertCommandOutputContains(a, "f.apply(2)", "==> 4")
+ );
+ }
+
+}
--- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_1.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_1.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, T6722234d.A,java.lang.Object, T6722234d.B,T6722234d.A)
+T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: T6722234d.A,java.lang.Object), (compiler.misc.lower.bounds: T6722234d.B,T6722234d.A))
- compiler.misc.where.description.typevar: Z,{(compiler.misc.where.typevar: Z, java.lang.Object, kindname.method, <Z>m(Z,Z))}
1 error
--- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_2.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_2.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, T6722234d.A,Object, T6722234d.B,T6722234d.A)
+T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: T6722234d.A,Object), (compiler.misc.lower.bounds: T6722234d.B,T6722234d.A))
- compiler.misc.where.description.typevar: Z,{(compiler.misc.where.typevar: Z, Object, kindname.method, <Z>m(Z,Z))}
1 error
--- a/test/langtools/tools/javac/Diagnostics/6799605/T6799605.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/Diagnostics/6799605/T6799605.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.incompatible.eq.upper.bounds: T, compiler.misc.type.captureof: 1, ?, T6799605<T>)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
+T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.incompatible.bounds: T, (compiler.misc.eq.bounds: compiler.misc.type.captureof: 1, ?), (compiler.misc.upper.bounds: T6799605<T>))),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
T6799605.java:18:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.incompatible.eq.bounds: T, compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
T6799605.java:19:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,T6799605<compiler.misc.type.captureof: 3, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.incompatible.eq.bounds: T, compiler.misc.type.captureof: 3, ?,compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?))}
3 errors
--- a/test/langtools/tools/javac/T8171325/NPEClearingLocalClassNameIndexesTest.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/T8171325/NPEClearingLocalClassNameIndexesTest.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,6 +1,6 @@
-NPEClearingLocalClassNameIndexesTest.java:18:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.upper.lower.bounds: C, java.lang.Object,java.util.List<A>, java.lang.String)
+NPEClearingLocalClassNameIndexesTest.java:18:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.bounds: C, (compiler.misc.upper.bounds: java.lang.Object,java.util.List<A>), (compiler.misc.lower.bounds: java.lang.String))
NPEClearingLocalClassNameIndexesTest.java:18:42: compiler.err.cant.resolve.location: kindname.class, NoSuch, , , (compiler.misc.location: kindname.class, NPEClearingLocalClassNameIndexesTest, null)
-NPEClearingLocalClassNameIndexesTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.upper.lower.bounds: C, java.lang.Object,java.util.List<A>, java.lang.String)
+NPEClearingLocalClassNameIndexesTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.bounds: C, (compiler.misc.upper.bounds: java.lang.Object,java.util.List<A>), (compiler.misc.lower.bounds: java.lang.String))
NPEClearingLocalClassNameIndexesTest.java:19:42: compiler.err.cant.resolve.location: kindname.class, NoSuch, , , (compiler.misc.location: kindname.class, NPEClearingLocalClassNameIndexesTest, null)
NPEClearingLocalClassNameIndexesTest.java:19:49: compiler.err.type.found.req: int, (compiler.misc.type.req.ref)
5 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8201281/NullInErrorMessageTest.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,30 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8201281
+ * @summary Truncated error message with Incompatible : null
+ * @compile/fail/ref=NullInErrorMessageTest.out -XDrawDiagnostics NullInErrorMessageTest.java
+ */
+
+import java.util.concurrent.CompletionStage;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class NullInErrorMessageTest {
+ private CompletionStage<String> test() {
+ return null;
+ }
+
+ private CompletionStage<Integer> test2() {
+ return null;
+ }
+
+ public static <T> Function<Throwable, T> test3() {
+ return null;
+ }
+
+ private Supplier<CompletionStage<Integer>> createSupplier() {
+ return () -> test().thenCompose(value -> {
+ return () -> test2().exceptionally(test3());
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8201281/NullInErrorMessageTest.out Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,2 @@
+NullInErrorMessageTest.java:26:40: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.not.a.functional.intf.1: java.util.concurrent.CompletionStage, (compiler.misc.incompatible.abstracts: kindname.interface, java.util.concurrent.CompletionStage)))))
+1 error
--- a/test/langtools/tools/javac/boxing/BoxingCaching.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/boxing/BoxingCaching.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4990346
+ * @bug 4990346 8200478
* @summary Verify autoboxed values are cached as required.
* @author Joseph D. Darcy
*/
@@ -155,7 +155,7 @@
Long L = (long)(i-128);
if (L != results[i]) {
cached = false;
- System.err.println("Integer value " + L +
+ System.err.println("Long value " + L +
" is not cached appropriately.");
}
}
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt Thu Apr 26 17:59:02 2018 +0200
@@ -73,7 +73,6 @@
compiler.misc.kindname.type.variable
compiler.misc.kindname.type.variable.bound
compiler.misc.kindname.value
-compiler.misc.incompatible.eq.lower.bounds # cannot happen?
compiler.misc.module.name.mismatch
compiler.misc.module.non.zero.opens # bad class file
compiler.misc.no.unique.minimal.instance.exists
@@ -151,6 +150,7 @@
compiler.misc.locn.module_source_path # fragment uninteresting in and of itself
compiler.misc.locn.system_modules # fragment uninteresting in and of itself
compiler.misc.locn.upgrade_module_path # fragment uninteresting in and of itself
+compiler.misc.inferred.do.not.conform.to.eq.bounds # hard to generate, could probably be removed
# The following are new module-related messages, that need new examples to be created
compiler.err.duplicate.module.on.path
--- a/test/langtools/tools/javac/diags/examples/CantApplyDiamond1.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/CantApplyDiamond1.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,7 +23,9 @@
// key: compiler.err.prob.found.req
// key: compiler.misc.cant.apply.diamond.1
-// key: compiler.misc.incompatible.eq.upper.bounds
+// key: compiler.misc.incompatible.bounds
+// key: compiler.misc.eq.bounds
+// key: compiler.misc.upper.bounds
// key: compiler.misc.diamond
class CantApplyDiamond1<X> {
--- a/test/langtools/tools/javac/diags/examples/IncompatibleEqUpperBounds.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/IncompatibleEqUpperBounds.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,7 +22,9 @@
*/
//key: compiler.err.cant.apply.symbol
-//key: compiler.misc.incompatible.eq.upper.bounds
+//key: compiler.misc.incompatible.bounds
+//key: compiler.misc.eq.bounds
+//key: compiler.misc.upper.bounds
import java.util.List;
--- a/test/langtools/tools/javac/diags/examples/InferredDoNotConformToEq.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/InferredDoNotConformToEq.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,7 +22,8 @@
*/
// key: compiler.err.cant.apply.symbol
-// key: compiler.misc.inferred.do.not.conform.to.eq.bounds
+// key: compiler.misc.inconvertible.types
+// key: compiler.misc.infer.no.conforming.assignment.exists
// options: -source 7 -Xlint:-options
import java.util.*;
--- a/test/langtools/tools/javac/diags/examples/InferredDoNotConformToUpper.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/InferredDoNotConformToUpper.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,7 +22,8 @@
*/
// key: compiler.err.cant.apply.symbol
-// key: compiler.misc.inferred.do.not.conform.to.upper.bounds
+// key: compiler.misc.inconvertible.types
+// key: compiler.misc.infer.no.conforming.assignment.exists
// options: -source 7 -Xlint:-options
import java.util.*;
--- a/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java Thu Apr 26 17:59:02 2018 +0200
@@ -21,10 +21,12 @@
* questions.
*/
-// key: compiler.misc.incompatible.upper.lower.bounds
+// key: compiler.misc.incompatible.bounds
// key: compiler.misc.where.description.typevar
// key: compiler.misc.where.typevar
// key: compiler.err.prob.found.req
+// key: compiler.misc.lower.bounds
+// key: compiler.misc.upper.bounds
// options: --diags=formatterOptions=where
// run: simple
--- a/test/langtools/tools/javac/generics/UnsoundInference.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/UnsoundInference.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-UnsoundInference.java:18:9: compiler.err.cant.apply.symbol: kindname.method, transferBug, Var[],java.util.Collection<Var>, java.lang.Object[],java.util.ArrayList<java.lang.String>, kindname.class, UnsoundInference, (compiler.misc.incompatible.eq.lower.bounds: Var, java.lang.String, java.lang.Object)
+UnsoundInference.java:18:9: compiler.err.cant.apply.symbol: kindname.method, transferBug, Var[],java.util.Collection<Var>, java.lang.Object[],java.util.ArrayList<java.lang.String>, kindname.class, UnsoundInference, (compiler.misc.incompatible.bounds: Var, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.lower.bounds: java.lang.Object))
1 error
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg06.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg06.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-Neg06.java:18:36: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.IFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
-Neg06.java:19:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
-Neg06.java:20:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
+Neg06.java:18:36: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.IFoo), (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number)))
+Neg06.java:19:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number)))
+Neg06.java:20:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number)))
3 errors
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg07.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg07.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-Neg07.java:17:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String)
-Neg07.java:18:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String)
+Neg07.java:17:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String))
+Neg07.java:18:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String))
2 errors
--- a/test/langtools/tools/javac/generics/inference/4941882/T4941882.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/4941882/T4941882.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T4941882.java:13:17: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: T, java.lang.Object[],java.lang.Object, float[],int[])
+T4941882.java:13:17: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: java.lang.Object[],java.lang.Object), (compiler.misc.lower.bounds: float[],int[]))
1 error
--- a/test/langtools/tools/javac/generics/inference/6315770/T6315770.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6315770/T6315770.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
T6315770.java:16:42: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: T, java.lang.String,java.lang.Integer,java.lang.Runnable)
-T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: T, java.lang.Integer,java.lang.Runnable, java.lang.String)
+T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: java.lang.Integer,java.lang.Runnable), (compiler.misc.lower.bounds: java.lang.String))
2 errors
--- a/test/langtools/tools/javac/generics/inference/6611449/T6611449.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6611449/T6611449.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
-T6611449.java:18:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.infer.arg.length.mismatch: T))}
-T6611449.java:19:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer))}
-T6611449.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, T, int, kindname.class, T6611449<S>, (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer)
-T6611449.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, T,T, int,int, kindname.class, T6611449<S>, (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer)
+T6611449.java:18:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.infer.arg.length.mismatch: T))}
+T6611449.java:19:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer)))}
+T6611449.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, T, int, kindname.class, T6611449<S>, (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer))
+T6611449.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, T,T, int,int, kindname.class, T6611449<S>, (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer))
4 errors
--- a/test/langtools/tools/javac/generics/inference/6638712/T6638712b.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6638712/T6638712b.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: T, java.lang.Integer, java.lang.String,java.lang.Object)
+T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: T, (compiler.misc.eq.bounds: java.lang.Integer), (compiler.misc.upper.bounds: java.lang.String,java.lang.Object))
1 error
--- a/test/langtools/tools/javac/generics/inference/6638712/T6638712d.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6638712/T6638712d.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.incompatible.eq.lower.bounds: U, java.lang.String, java.lang.Integer)
+T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.incompatible.bounds: U, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.lower.bounds: java.lang.Integer))
1 error
--- a/test/langtools/tools/javac/generics/inference/6638712/T6638712e.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6638712/T6638712e.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Boolean,java.lang.Object)
+T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Object), (compiler.misc.upper.bounds: java.lang.Boolean,java.lang.Object))
1 error
--- a/test/langtools/tools/javac/generics/inference/6650759/T6650759m.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6650759/T6650759m.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Integer,java.lang.Object, java.lang.String)
+T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Integer,java.lang.Object), (compiler.misc.lower.bounds: java.lang.String))
1 error
--- a/test/langtools/tools/javac/generics/inference/7177306/T7177306b.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/7177306/T7177306b.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T7177306b.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<? super T>,S,java.lang.Class<java.lang.Object>, java.util.List<java.lang.Integer>,java.util.List<java.lang.String>,java.lang.Class, kindname.class, T7177306b, (compiler.misc.incompatible.eq.upper.bounds: T, java.lang.String, java.lang.Integer,java.lang.Object)
+T7177306b.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<? super T>,S,java.lang.Class<java.lang.Object>, java.util.List<java.lang.Integer>,java.util.List<java.lang.String>,java.lang.Class, kindname.class, T7177306b, (compiler.misc.incompatible.bounds: T, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Integer,java.lang.Object))
1 error
--- a/test/langtools/tools/javac/generics/inference/7177306/T7177306e.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/7177306/T7177306e.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T7177306e.java:16:8: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<U>, java.util.List<java.util.List<?>>, kindname.class, T7177306e, (compiler.misc.incompatible.eq.upper.bounds: U, java.util.List<?>, java.util.List<compiler.misc.type.captureof: 1, ?>)
+T7177306e.java:16:8: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<U>, java.util.List<java.util.List<?>>, kindname.class, T7177306e, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Object, compiler.misc.type.captureof: 1, ?)
1 error
--- a/test/langtools/tools/javac/generics/inference/8019824/T8019824.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/8019824/T8019824.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T8019824.java:9:25: compiler.err.cant.apply.symbol: kindname.method, make, java.lang.Class<C>, java.lang.Class<compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>>, kindname.class, T8019824, (compiler.misc.incompatible.eq.upper.bounds: C, compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>, T8019824.Foo<A,B>)
+T8019824.java:9:25: compiler.err.cant.apply.symbol: kindname.method, make, java.lang.Class<C>, java.lang.Class<compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>>, kindname.class, T8019824, (compiler.misc.incompatible.bounds: C, (compiler.misc.eq.bounds: compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>), (compiler.misc.upper.bounds: T8019824.Foo<A,B>))
1 error
--- a/test/langtools/tools/javac/generics/inference/8062977/T8062977.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/8062977/T8062977.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
-T8062977.java:15:31: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List<java.lang.Integer>[]&java.lang.Iterable<?>, java.util.List<java.lang.Integer>[],java.lang.Iterable<?>,java.lang.Object)
-T8062977.java:21:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Iterable<?>[]&java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>,java.lang.Iterable<?>[],java.lang.Object)
-T8062977.java:26:31: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List<java.lang.Integer>[], java.util.List<java.lang.Integer>[],java.lang.Iterable<?>[][],java.lang.Object)
-T8062977.java:27:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Iterable<?>[][]&java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>,java.lang.Iterable<?>[][],java.lang.Object)
+T8062977.java:15:31: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>>, java.lang.Class<java.lang.Object>))
+T8062977.java:21:29: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>[]>, java.lang.Class<java.lang.Object>))
+T8062977.java:26:31: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>[][]>, java.lang.Class<java.lang.Object>))
+T8062977.java:27:29: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>[][]>, java.lang.Class<java.lang.Object>))
4 errors
--- a/test/langtools/tools/javac/generics/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-PrimitiveTypeBoxingTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, m1, PrimitiveTypeBoxingTest.F<Z>,Z, @12,int, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Long,java.lang.Object, java.lang.Integer)
-PrimitiveTypeBoxingTest.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m2, Z,PrimitiveTypeBoxingTest.F<Z>, int,@16, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Long,java.lang.Object, java.lang.Integer)
+PrimitiveTypeBoxingTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, m1, PrimitiveTypeBoxingTest.F<Z>,Z, @12,int, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Long,java.lang.Object), (compiler.misc.lower.bounds: java.lang.Integer))
+PrimitiveTypeBoxingTest.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m2, Z,PrimitiveTypeBoxingTest.F<Z>, int,@16, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Long,java.lang.Object), (compiler.misc.lower.bounds: java.lang.Integer))
2 errors
--- a/test/langtools/tools/javac/generics/odersky/BadTest3.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/odersky/BadTest3.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-BadTest3.java:31:34: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: B, java.lang.String, BadTest3.Ord)
-BadTest3.java:33:13: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.upper.lower.bounds: B, BadTest3.I,BadTest3.J, List<B>)
-BadTest3.java:35:19: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.upper.lower.bounds: B, BadTest3.I,BadTest3.J, List<B>)
+BadTest3.java:31:34: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: B, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: BadTest3.Ord))
+BadTest3.java:33:13: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.bounds: B, (compiler.misc.upper.bounds: BadTest3.I,BadTest3.J), (compiler.misc.lower.bounds: List<B>))
+BadTest3.java:35:19: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.bounds: B, (compiler.misc.upper.bounds: BadTest3.I,BadTest3.J), (compiler.misc.lower.bounds: List<B>))
3 errors
--- a/test/langtools/tools/javac/generics/wildcards/6762569/T6762569b.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/wildcards/6762569/T6762569b.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6762569b.java:13:9: compiler.err.cant.apply.symbol: kindname.method, m, T,java.util.List<? super java.util.List<T>>, java.lang.String,java.util.List<compiler.misc.type.captureof: 1, ? super java.util.List<? extends java.lang.Number>>, kindname.class, T6762569b, (compiler.misc.incompatible.upper.lower.bounds: T, java.lang.Number,java.lang.Object, java.lang.String)
+T6762569b.java:13:9: compiler.err.cant.apply.symbol: kindname.method, m, T,java.util.List<? super java.util.List<T>>, java.lang.String,java.util.List<compiler.misc.type.captureof: 1, ? super java.util.List<? extends java.lang.Number>>, kindname.class, T6762569b, (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: java.lang.Number,java.lang.Object), (compiler.misc.lower.bounds: java.lang.String))
1 error
--- a/test/langtools/tools/javac/lambda/8016177/T8016177g.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/8016177/T8016177g.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-T8016177g.java:34:14: compiler.err.cant.apply.symbol: kindname.method, print, java.lang.String, Test.Person, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.upper.lower.bounds: R, java.lang.String,java.lang.Object, Test.Person))
+T8016177g.java:34:14: compiler.err.cant.apply.symbol: kindname.method, print, java.lang.String, Test.Person, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.bounds: R, (compiler.misc.upper.bounds: java.lang.String,java.lang.Object), (compiler.misc.lower.bounds: Test.Person)))
T8016177g.java:35:20: compiler.err.cant.apply.symbol: kindname.method, abs, int, java.lang.Double, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Double, java.lang.Integer,java.lang.Object))
2 errors
--- a/test/langtools/tools/javac/lambda/MethodReference41.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference41.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference41.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference41.SAM1, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String))))
-MethodReference41.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference41.SAM3, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference41.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference41.SAM1, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String)))))
+MethodReference41.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference41.SAM3, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
MethodReference41.java:41:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference41.SAM2), MethodReference41, kindname.method, m4(MethodReference41.SAM3), MethodReference41
3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference42.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference42.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference42.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference42.SAM1, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number)))
-MethodReference42.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference42.SAM3, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number)))
+MethodReference42.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference42.SAM1, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number))))
+MethodReference42.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference42.SAM3, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Object), (compiler.misc.upper.bounds: java.lang.Number))))
MethodReference42.java:41:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference42.SAM2), MethodReference42, kindname.method, m4(MethodReference42.SAM3), MethodReference42
3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference43.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference43.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
-MethodReference43.java:45:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference43.SAM1, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String))))
-MethodReference43.java:47:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference43.java:45:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference43.SAM1, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String)))))
+MethodReference43.java:47:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
MethodReference43.java:49:9: compiler.err.ref.ambiguous: m5, kindname.method, m5(MethodReference43.SAM3), MethodReference43, kindname.method, m5(MethodReference43.SAM4), MethodReference43
-MethodReference43.java:49:11: compiler.err.cant.apply.symbol: kindname.method, m5, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference43.java:49:11: compiler.err.cant.apply.symbol: kindname.method, m5, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
4 errors
--- a/test/langtools/tools/javac/lambda/MethodReference44.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference44.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference44.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference44.SAM1, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number)))
-MethodReference44.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference44.SAM3, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number)))
+MethodReference44.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference44.SAM1, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number))))
+MethodReference44.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference44.SAM3, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Object), (compiler.misc.upper.bounds: java.lang.Number))))
MethodReference44.java:43:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference44.SAM2), MethodReference44, kindname.method, g4(MethodReference44.SAM3), MethodReference44
3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference46.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference46.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference46.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference46.SAM1, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.String, kindname.class, MethodReference46, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String))))
-MethodReference46.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference46.SAM3, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.Object, kindname.class, MethodReference46, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference46.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference46.SAM1, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.String, kindname.class, MethodReference46, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String)))))
+MethodReference46.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference46.SAM3, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.Object, kindname.class, MethodReference46, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
MethodReference46.java:43:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference46.SAM2), MethodReference46, kindname.method, g4(MethodReference46.SAM3), MethodReference46
3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference58.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference58.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-MethodReference58.java:41:23: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, Z, X, kindname.class, MethodReference58, (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Number, X)))
+MethodReference58.java:41:23: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, Z, X, kindname.class, MethodReference58, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: X))))
1 error
--- a/test/langtools/tools/javac/lambda/MethodReference68.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference68.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @12,int, kindname.class, MethodReference68, (compiler.misc.incompatible.upper.lower.bounds: Z, MethodReference68.Foo,java.lang.Object, java.lang.Integer)
-1 error
\ No newline at end of file
+MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @12,int, kindname.class, MethodReference68, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: MethodReference68.Foo,java.lang.Object), (compiler.misc.lower.bounds: java.lang.Integer))
+1 error
--- a/test/langtools/tools/javac/lambda/TargetType02.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/TargetType02.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-TargetType02.java:33:14: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.String, java.lang.Integer)
+TargetType02.java:33:14: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.String), (compiler.misc.lower.bounds: java.lang.Integer))
TargetType02.java:34:9: compiler.err.ref.ambiguous: call3, kindname.method, <Z>call3(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call3(TargetType02.S2<Z>), TargetType02
TargetType02.java:35:9: compiler.err.ref.ambiguous: call3, kindname.method, <Z>call3(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call3(TargetType02.S2<Z>), TargetType02
TargetType02.java:37:20: compiler.err.ref.ambiguous: call4, kindname.method, <Z>call4(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call4(TargetType02.S2<Z>), TargetType02
--- a/test/langtools/tools/javac/lambda/TargetType14.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/TargetType14.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.lower.bounds: X, java.lang.Integer, java.lang.String)
+TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Integer), (compiler.misc.lower.bounds: java.lang.String))
1 error
--- a/test/langtools/tools/javac/lambda/TargetType28.out Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/TargetType28.out Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Object,java.lang.Number)
+TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Object,java.lang.Number))
1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/deduplication/ClassFieldDeduplication.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8202141
+ * @summary Verify that .class synthetic Symbols are not duplicated.
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.tree
+ * jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main ClassFieldDeduplication
+ */
+
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.TreeScanner;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTestHelper;
+
+public class ClassFieldDeduplication extends ComboInstance<ClassFieldDeduplication> {
+
+ enum Type implements ComboParameter {
+ OBJECT("Object"),
+ PRIMITIVE("int"),
+ BOXED_PRIMITIVE("Integer"),
+ VOID("void"),
+ BOXED_VOID("Void"),
+ OBJECT_ARRAY("Object[]"),
+ PRIMITIVE_ARRAY("int[]"),
+ BOXED_PRIMITIVE_ARRAY("Integer[]"),
+ BOXED_VOID_ARRAY("Void[]");
+
+ String type;
+
+ Type(String type) {
+ this.type = type;
+ }
+
+ @Override
+ public String expand(String optParameter) {
+ return type;
+ }
+
+ }
+
+ public static void main(String... args) throws Exception {
+ new ComboTestHelper<ClassFieldDeduplication>()
+ .withDimension("TYPE", Type.values())
+ .run(ClassFieldDeduplication::new);
+ }
+
+ private static final String TEMPLATE =
+ "class Test { void t() { Object o1 = #{TYPE}.class; Object o2 = #{TYPE}.class; } }";
+
+ @Override
+ protected void doWork() throws Throwable {
+ newCompilationTask()
+ .withSourceFromTemplate(TEMPLATE)
+ .withListener(new TaskListener() {
+ JCCompilationUnit cut;
+ @Override
+ public void finished(TaskEvent e) {
+ if (e.getKind() == TaskEvent.Kind.PARSE) {
+ if (cut != null)
+ throw new AssertionError();
+ cut = (JCCompilationUnit) e.getCompilationUnit();
+ }
+ if (e.getKind() == TaskEvent.Kind.ANALYZE) {
+ cut.accept(new TreeScanner() {
+ Symbol s;
+ @Override
+ public void visitSelect(JCFieldAccess tree) {
+ if (tree.name.contentEquals("class")) {
+ if (s == null) {
+ s = tree.sym;
+ } else if (s != tree.sym) {
+ throw new AssertionError("Duplicated field symbol.");
+ }
+ }
+ super.visitSelect(tree);
+ }
+ });
+ }
+ }
+
+ })
+ .analyze(els -> {});
+ }
+
+}
--- a/test/langtools/tools/javac/lambda/deduplication/Deduplication.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/deduplication/Deduplication.java Thu Apr 26 17:59:02 2018 +0200
@@ -38,6 +38,31 @@
(Runnable) () -> { ( (Runnable) () -> {} ).run(); }
);
+ group(
+ (Runnable) () -> { Deduplication.class.toString(); },
+ (Runnable) () -> { Deduplication.class.toString(); }
+ );
+
+ group(
+ (Runnable) () -> { Integer[].class.toString(); },
+ (Runnable) () -> { Integer[].class.toString(); }
+ );
+
+ group(
+ (Runnable) () -> { char.class.toString(); },
+ (Runnable) () -> { char.class.toString(); }
+ );
+
+ group(
+ (Runnable) () -> { Void.class.toString(); },
+ (Runnable) () -> { Void.class.toString(); }
+ );
+
+ group(
+ (Runnable) () -> { void.class.toString(); },
+ (Runnable) () -> { void.class.toString(); }
+ );
+
group((Function<String, Integer>) x -> x.hashCode());
group((Function<Object, Integer>) x -> x.hashCode());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/lib/builder/AbstractBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package builder;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class AbstractBuilder {
+
+ final String name;
+
+ Modifiers modifiers;
+ Comment comments;
+ String cname;
+
+ /**
+ * Constructs the base builder.
+ * @param modifiers for the class
+ * @param name of the element
+ */
+ public AbstractBuilder(Modifiers modifiers, String name) {
+ this.modifiers = modifiers;
+ this.name = name;
+ this.comments = new Comment(Comment.Kind.AUTO);
+ }
+
+ AbstractBuilder setModifiers(String... mods) {
+ this.modifiers = new Modifiers(mods);
+ return this;
+ }
+
+ /**
+ * Sets the enclosing type's name.
+ * @param className the enclosing type's name
+ */
+ void setClassName(String className) {
+ this.cname = className;
+ }
+
+ /**
+ * Sets the comment type for the member.
+ * @param comment for the member.
+ * @return this builder.
+ */
+ public AbstractBuilder setComments(Comment comment) {
+ this.comments = comment;
+ return this;
+ }
+
+ /**
+ * Sets the comments for the member.
+ * @param comments for the member.
+ * @return this builder.
+ */
+ public AbstractBuilder setComments(String... comments) {
+ this.comments = new Comment(comments);
+ return this;
+ }
+
+ /**
+ * Sets a comment for the element. Typically used to set
+ * user's preferences whether an automatic comment is
+ * required or no API comment.
+ *
+ * @param kind of comment, automatic or no comment.
+ * @return this builder.
+ */
+ public AbstractBuilder setComments(Comment.Kind kind) {
+ switch (kind) {
+ case NO_API_COMMENT: case AUTO: case INHERIT_DOC:
+ this.comments = new Comment(kind);
+ break;
+ default:
+ throw new IllegalArgumentException(kind + " not allowed");
+ }
+ return this;
+ }
+
+ /**
+ * The comment container.
+ */
+ public static class Comment {
+
+ /**
+ * The kinds of a comment.
+ */
+ public enum Kind {
+ /**
+ * user specified
+ */
+ USER,
+ /**
+ * no API comments
+ */
+ NO_API_COMMENT,
+ /**
+ * inserts the javadoc tag
+ */
+ INHERIT_DOC,
+ /**
+ * auto generate one
+ */
+ AUTO
+ }
+
+ final Kind kind;
+ final List<String> comments;
+
+ /**
+ * Construct an initial comment.
+ *
+ * @param kind
+ */
+ public Comment(Kind kind) {
+ this.kind = kind;
+ comments = Collections.emptyList();
+ }
+
+ /**
+ * Specify a user comment.
+ *
+ * @param comments the string of API comments.
+ */
+ public Comment(String... comments) {
+ kind = Kind.USER;
+ this.comments = comments == null
+ ? Collections.emptyList()
+ : List.of(comments);
+ }
+
+ @Override
+ public String toString() {
+ ClassBuilder.OutputWriter ow = new ClassBuilder.OutputWriter();
+ switch (kind) {
+ case USER:
+ comments.forEach((s) -> ow.println(" " + s));
+ break;
+ case INHERIT_DOC:
+ ow.println("{@inheritDoc}");
+ break;
+ }
+ return ow.toString();
+ }
+ }
+
+ /**
+ * The modifier representation for an element.
+ */
+ public static class Modifiers {
+ List<String> modifiers;
+
+ /**
+ * Constructs a modifier container.
+ * @param modifiers for an element.
+ */
+ public Modifiers(String... modifiers) {
+ this.modifiers = List.of(modifiers);
+ }
+
+ /**
+ * Constructs a modifier container.
+ * @param modifiers a list of modifier strings.
+ */
+ public Modifiers(List<String> modifiers) {
+ this.modifiers = modifiers;
+ }
+
+ /**
+ * Sets the modifiers for this element.
+ * @param modifiers
+ */
+ public void setModifiers(String... modifiers) {
+ this.modifiers = List.of(modifiers);
+ }
+
+ /**
+ * Sets the modifiers for this element.
+ * @param modifiers
+ */
+ public void setModifiers(List<String> modifiers) {
+ this.modifiers = modifiers;
+ }
+
+ @Override
+ public String toString() {
+ OutputWriter ow = new OutputWriter();
+ modifiers.forEach(i -> ow.print(i + " "));
+ return ow.toString();
+ }
+ }
+
+ /**
+ * The output writer.
+ */
+ public static class OutputWriter {
+ private final StringWriter sw = new StringWriter();
+ private final PrintWriter pw = new PrintWriter(sw);
+
+ @Override
+ public String toString() {
+ return sw.getBuffer().toString();
+ }
+
+ /**
+ * Prints a string without NL.
+ * @param s the string to print.
+ */
+ public void print(String s) {
+ pw.print(s);
+ }
+
+ /**
+ * Prints a string with a NL.
+ * @param s the string to print.
+ */
+ public void println(String s) {
+ pw.println(s);
+ }
+ }
+
+ /**
+ * A container to encapsulate a pair of values.
+ */
+ public static class Pair {
+ final String first;
+ final String second;
+
+ public Pair(String first, String second) {
+ this.first = first;
+ this.second = second;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/lib/builder/ClassBuilder.java Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package builder;
+
+import toolbox.ToolBox;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Builder for type declarations.
+ * Note: this implementation does not support everything and is not
+ * exhaustive.
+ */
+public class ClassBuilder extends AbstractBuilder {
+
+ private final ToolBox tb;
+ private final String fqn;
+ private final String clsname;
+ private final String typeParameter;
+
+ private String pkg;
+ private final List<String> imports;
+
+ private String extendsType;
+ private final List<String> implementsTypes;
+ private final List<MemberBuilder> members;
+ private final List<ClassBuilder> inners;
+ private final List<ClassBuilder> nested;
+
+
+ final static Pattern CLASS_RE = Pattern.compile("(.*)(<.*>)");
+
+ /**
+ * Creates a class builder.
+ * @param tb the toolbox reference
+ * @param name the name of the type
+ */
+ public ClassBuilder(ToolBox tb, String name) {
+ super(new Modifiers(), name);
+ this.tb = tb;
+
+ Matcher m = CLASS_RE.matcher(name);
+ if (m.matches()) {
+ fqn = m.group(1);
+ typeParameter = m.group(2);
+ } else {
+ fqn = name;
+ typeParameter = null;
+ }
+ if (fqn.contains(".")) {
+ this.pkg = name.substring(0, fqn.lastIndexOf('.'));
+ clsname = fqn.substring(fqn.lastIndexOf('.') + 1);
+ } else {
+ clsname = fqn;
+ }
+ imports = new ArrayList<>();
+ implementsTypes = new ArrayList<>();
+ members = new ArrayList<>();
+ nested = new ArrayList<>();
+ inners = new ArrayList<>();
+ }
+
+ /**
+ * Adds an import(s).
+ * @param i the import type.
+ * @return this builder.
+ */
+ public ClassBuilder addImports(String i) {
+ imports.add(i);
+ return this;
+ }
+
+ /**
+ * Sets the modifiers for this builder.
+ * @param modifiers the modifiers
+ * @return this builder
+ */
+ public ClassBuilder setModifiers(String... modifiers) {
+ this.modifiers.setModifiers(modifiers);
+ return this;
+ }
+
+ /**
+ * Sets the enclosing type's name.
+ *
+ * @param className the enclosing type's name
+ */
+ @Override
+ void setClassName(String className) {
+ cname = className;
+ }
+
+ /**
+ * Sets a comment for the element.
+ *
+ * @param comments for the element
+ * @return this builder.
+ */
+ @Override
+ public ClassBuilder setComments(String... comments) {
+ super.setComments(comments);
+ return this;
+ }
+
+ /**
+ * Sets a comment for the element. Typically used to set
+ * the user's preferences whether an automatic comment is
+ * required or no API comment.
+ *
+ * @param kind of comment, automatic or no comment.
+ * @return this builder.
+ */
+ @Override
+ public ClassBuilder setComments(Comment.Kind kind) {
+ super.setComments(kind);
+ return this;
+ }
+
+ /**
+ * Set the super-type of the type.
+ * @param name of the super type.
+ * @return this builder.
+ */
+ public ClassBuilder setExtends(String name) {
+ extendsType = name;
+ return this;
+ }
+
+ /**
+ * Adds an implements declaration(s).
+ * @param names the interfaces
+ * @return this builder.
+ */
+ public ClassBuilder addImplements(String... names) {
+ implementsTypes.addAll(List.of(names));
+ return this;
+ }
+
+ /**
+ * Adds a member(s) to the class declaration.
+ * @param mbs the member builder(s) representing member(s).
+ * @return this builder
+ */
+ public ClassBuilder addMembers(MemberBuilder... mbs) {
+ for (MemberBuilder mb : mbs) {
+ members.add(mb);
+ mb.setClassName(fqn);
+ }
+ return this;
+ }
+
+ /**
+ * Adds nested-classes, to an outer class to an outer builder.
+ * @param cbs class builder(s) of the nested classes.
+ * @return this builder.
+ */
+ public ClassBuilder addNestedClasses(ClassBuilder... cbs) {
+ Stream.of(cbs).forEach(cb -> {
+ nested.add(cb);
+ cb.setClassName(fqn);
+ });
+ return this;
+ }
+
+ /**
+ * Adds inner-classes, to an an outer class builder.
+ * @param cbs class builder(s) of the inner classes.
+ * @return this builder.
+ */
+ public ClassBuilder addInnerClasses(ClassBuilder... cbs) {
+ Stream.of(cbs).forEach(cb -> {
+ inners.add(cb);
+ cb.setClassName(fqn);
+ });
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ OutputWriter ow = new OutputWriter();
+ if (pkg != null)
+ ow.println("package " + pkg + ";");
+ imports.forEach(i -> ow.println("import " + i + ";"));
+ switch (comments.kind) {
+ case AUTO:
+ ow.println("/** Class " + fqn + " */");
+ break;
+ case USER:
+ ow.println("/** ");
+ comments.comments.forEach(c -> ow.println(" * " + c));
+ ow.println(" */");
+ break;
+ case NO_API_COMMENT:
+ ow.println("// NO_API_COMMENT");
+ break;
+ }
+ ow.print(modifiers.toString());
+ ow.print(clsname);
+ if (typeParameter != null) {
+ ow.print(typeParameter + " ");
+ } else {
+ ow.print(" ");
+ }
+ if (extendsType != null && !extendsType.isEmpty()) {
+ ow.print("extends " + extendsType + " ");
+ }
+ if (!implementsTypes.isEmpty()) {
+ ow.print("implements ");
+
+ ListIterator<String> iter = implementsTypes.listIterator();
+ while (iter.hasNext()) {
+ String s = iter.next() ;
+ ow.print(s);
+ if (iter.hasNext())
+ ow.print(", ");
+ }
+ }
+ ow.print("{");
+ if (!nested.isEmpty()) {
+ ow.println("");
+ nested.forEach(m -> ow.println(m.toString()));
+ }
+
+ if (!members.isEmpty()) {
+ ow.println("");
+ members.forEach(m -> ow.println(m.toString()));
+ }
+
+ ow.println("}");
+ if (!inners.isEmpty()) {
+ ow.println(" {");
+ inners.forEach(m -> ow.println(m.toString()));
+ ow.println("}");
+ }
+ return ow.toString();
+ }
+
+ /**
+ * Writes out the java source for a type element. Package directories
+ * will be created as needed as inferred by the type name.
+ * @param srcDir the top level source directory.
+ * @throws IOException if an error occurs.
+ */
+ public void write(Path srcDir) throws IOException {
+ Files.createDirectories(srcDir);
+ Path outDir = srcDir;
+ if (pkg != null && !pkg.isEmpty()) {
+ String pdir = pkg.replace(".", "/");
+ outDir = Paths.get(srcDir.toString(), pdir);
+ Files.createDirectories(outDir);
+ }
+ Path filePath = Paths.get(outDir.toString(), clsname + ".java");
+ tb.writeFile(filePath, this.toString());
+ }
+
+ /**
+ * The member builder, this is the base class for all types of members.
+ */
+ public static abstract class MemberBuilder extends AbstractBuilder {
+ public MemberBuilder(Modifiers modifiers, String name) {
+ super(modifiers, name);
+ }
+
+ /**
+ * Sets the enclosing type's name.
+ * @param className the enclosing type's name
+ */
+ @Override
+ void setClassName(String className) {
+ cname = className;
+ }
+
+ /**
+ * Sets a comment for the element.
+ *
+ * @param comments for any element
+ * @return this builder.
+ */
+ @Override
+ public MemberBuilder setComments(String... comments) {
+ super.setComments(comments);
+ return this;
+ }
+
+ /**
+ * Sets a comment for the element. Typically used to set user's
+ * preferences whether an automatic comment is required or no API
+ * comment.
+ *
+ * @param kind of comment, automatic or no comment.
+ * @return this builder.
+ */
+ @Override
+ public MemberBuilder setComments(Comment.Kind kind) {
+ super.setComments(kind);
+ return this;
+ }
+
+ /**
+ * Sets a new modifier.
+ *
+ * @param modifiers
+ * @return this builder.
+ */
+ @Override
+ public MemberBuilder setModifiers(String... modifiers) {
+ super.setModifiers(modifiers);
+ return this;
+ }
+ }
+
+ /**
+ * The field builder.
+ */
+ public static class FieldBuilder extends MemberBuilder {
+ private String fieldType;
+ private String value;
+
+ private static final Pattern FIELD_RE = Pattern.compile("(.*)(\\s*=\\s*)(.*)(;)");
+
+ /**
+ * Constructs a field with the modifiers and name of the field.
+ * The builder by default is configured to auto generate the
+ * comments for the field.
+ * @param name of the field
+ */
+ public FieldBuilder(String name) {
+ super(new Modifiers(), name);
+ this.comments = new Comment(Comment.Kind.AUTO);
+ }
+
+ /**
+ * Returns a field builder by parsing the string.
+ * ex: public static String myPlayingField;
+ * @param fieldString describing the field.
+ * @return a field builder.
+ */
+ public static FieldBuilder parse(String fieldString) {
+ String prefix;
+ String value = null;
+ Matcher m = FIELD_RE.matcher(fieldString);
+ if (m.matches()) {
+ prefix = m.group(1).trim();
+ value = m.group(3).trim();
+ } else {
+ int end = fieldString.lastIndexOf(';') > 0
+ ? fieldString.lastIndexOf(';')
+ : fieldString.length();
+ prefix = fieldString.substring(0, end).trim();
+ }
+ List<String> list = Stream.of(prefix.split(" "))
+ .filter(s -> !s.isEmpty()).collect(Collectors.toList());
+ if (list.size() < 2) {
+ throw new IllegalArgumentException("incorrect field string: "
+ + fieldString);
+ }
+ String name = list.get(list.size() - 1);
+ String fieldType = list.get(list.size() - 2);
+
+ FieldBuilder fb = new FieldBuilder(name);
+ fb.modifiers.setModifiers(list.subList(0, list.size() - 2));
+ fb.setFieldType(fieldType);
+ if (value != null)
+ fb.setValue(value);
+
+ return fb;
+ }
+
+ /**
+ * Sets the modifiers for this builder.
+ *
+ * @param mods
+ * @return this builder
+ */
+ public FieldBuilder setModifiers(String mods) {
+ this.modifiers.setModifiers(mods);
+ return this;
+ }
+
+ /**
+ * Sets the type of the field.
+ * @param fieldType the name of the type.
+ * @return this field builder.
+ */
+ public FieldBuilder setFieldType(String fieldType) {
+ this.fieldType = fieldType;
+ return this;
+ }
+
+ public FieldBuilder setValue(String value) {
+ this.value = value;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ String indent = " ";
+ OutputWriter ow = new OutputWriter();
+ switch (comments.kind) {
+ case AUTO:
+ ow.println(indent + "/** Field " +
+ super.name + " in " + super.cname + " */");
+ break;
+ case INHERIT_DOC: case USER:
+ ow.println(indent + "/** " +
+ comments.toString() + " */");
+ break;
+ case NO_API_COMMENT:
+ ow.println(indent + "// NO_API_COMMENT");
+ break;
+ }
+ ow.print(indent + super.modifiers.toString() + " ");
+ ow.print(fieldType + " ");
+ ow.print(super.name);
+ if (value != null) {
+ ow.print(" = " + value);
+ }
+ ow.println(";");
+ return ow.toString();
+ }
+ }
+
+ /**
+ * The method builder.
+ */
+ public static class MethodBuilder extends MemberBuilder {
+
+ private final List<Pair> params;
+
+ private String returnType;
+ private List<String> body;
+
+ final static Pattern METHOD_RE = Pattern.compile("(.*)(\\()(.*)(\\))(.*)");
+
+ /**
+ * Constructs a method builder. The builder by default is configured
+ * to auto generate the comments for this method.
+ * @param name of the method.
+ */
+ public MethodBuilder(String name) {
+ super(new Modifiers(), name);
+ comments = new Comment(Comment.Kind.AUTO);
+ params = new ArrayList<>();
+ body = null;
+ }
+
+ /**
+ * Returns a method builder by parsing a string which
+ * describes a method.
+ * @param methodString the method description.
+ * @return a method builder.
+ */
+ public static MethodBuilder parse(String methodString) {
+ Matcher m = METHOD_RE.matcher(methodString);
+ if (!m.matches())
+ throw new IllegalArgumentException("string does not match: "
+ + methodString);
+ String prefix = m.group(1);
+ String params = m.group(3);
+ String suffix = m.group(5).trim();
+
+ if (prefix.length() < 2) {
+ throw new IllegalArgumentException("incorrect method string: "
+ + methodString);
+ }
+
+ String[] pa = prefix.split(" ");
+ List<String> list = List.of(pa);
+ String name = list.get(list.size() - 1);
+ String returnType = list.get(list.size() - 2);
+
+ MethodBuilder mb = new MethodBuilder(name);
+ mb.modifiers.setModifiers(list.subList(0, list.size() - 2));
+ mb.setReturn(returnType);
+
+ pa = params.split(",");
+ Stream.of(pa).forEach(p -> {
+ p = p.trim();
+ if (!p.isEmpty())
+ mb.addParameter(p);
+ });
+ if (!suffix.isEmpty() || suffix.length() > 1) {
+ mb.setBody(suffix);
+ }
+ return mb;
+ }
+
+ /**
+ * Sets the modifiers for this builder.
+ *
+ * @param modifiers
+ * @return this builder
+ */
+ public MethodBuilder setModifiers(String modifiers) {
+ this.modifiers.setModifiers(modifiers);
+ return this;
+ }
+
+ @Override
+ public MethodBuilder setComments(String... comments) {
+ super.setComments(comments);
+ return this;
+ }
+
+ @Override
+ public MethodBuilder setComments(Comment.Kind kind) {
+ super.setComments(kind);
+ return this;
+ }
+
+ /**
+ * Sets a return type for a method.
+ * @param returnType the return type.
+ * @return this method builder.
+ */
+ public MethodBuilder setReturn(String returnType) {
+ this.returnType = returnType;
+ return this;
+ }
+
+ /**
+ * Adds a parameter(s) to the method method builder.
+ * @param params a pair consisting of type and parameter name.
+ * @return this method builder.
+ */
+ public MethodBuilder addParameters(Pair... params) {
+ this.params.addAll(List.of(params));
+ return this;
+ }
+
+ /**
+ * Adds a parameter to the method method builder.
+ * @param type the type of parameter.
+ * @param name the parameter name.
+ * @return this method builder.
+ */
+ public MethodBuilder addParameter(String type, String name) {
+ this.params.add(new Pair(type, name));
+ return this;
+ }
+
+ /**
+ * Adds a parameter to the method builder, by parsing the string.
+ * @param s the parameter description such as "Double voltage"
+ * @return this method builder.
+ */
+ public MethodBuilder addParameter(String s) {
+ String[] p = s.trim().split(" ");
+ return addParameter(p[0], p[p.length - 1]);
+ }
+
+ /**
+ * Sets the body of the method, described by the string.
+ * Such as "{", "double i = v/r;", "return i;", "}"
+ * @param body of the methods
+ * @return
+ */
+ public MethodBuilder setBody(String... body) {
+ if (body == null) {
+ this.body = null;
+ } else {
+ this.body = new ArrayList<>();
+ this.body.addAll(List.of(body));
+ }
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ OutputWriter ow = new OutputWriter();
+ String indent = " ";
+ switch (comments.kind) {
+ case AUTO:
+ ow.println(indent + "/** Method " + super.name + " in " + super.cname);
+ if (!params.isEmpty())
+ params.forEach(p -> ow.println(indent + " * @param " + p.second + " a param"));
+ if (returnType != null && !returnType.isEmpty() && !returnType.contains("void"))
+ ow.println(indent + " * @return returns something");
+ ow.println(indent + " */");
+ break;
+ case INHERIT_DOC: case USER:
+ ow.println(indent + "/** " + comments.toString() + " */");
+ break;
+ case NO_API_COMMENT:
+ ow.println(indent + "// NO_API_COMMENT");
+ break;
+ }
+
+ ow.print(indent + super.modifiers.toString() + " ");
+ ow.print(returnType + " ");
+ ow.print(super.name + "(");
+ if (!params.isEmpty()) {
+ ListIterator<Pair> iter = params.listIterator();
+ while (iter.hasNext()) {
+ Pair p = iter.next();
+ ow.print(p.first + " " + p.second);
+ if (iter.hasNext())
+ ow.print(", ");
+ }
+ }
+ ow.print(")");
+ if (body == null) {
+ ow.println(";");
+ } else {
+ body.forEach(ow::println);
+ }
+ return ow.toString();
+ }
+ }
+
+//A sample, to test with an IDE.
+// public static void main(String... args) throws IOException {
+// ClassBuilder cb = new ClassBuilder(new ToolBox(), "foo.bar.Test<C extends A>");
+// cb.addModifiers("public", "abstract", "static")
+// .addImports("java.io").addImports("java.nio")
+// .setComments("A comment")
+// .addImplements("Serialization", "Something")
+// .setExtends("java.lang.Object")
+// .addMembers(
+// FieldBuilder.parse("public int xxx;"),
+// FieldBuilder.parse("public int yyy = 10;"),
+// MethodBuilder.parse("public static void main(A a, B b, C c);")
+// .setComments("CC"),
+// MethodBuilder.parse("void foo(){//do something}")
+//
+// );
+// ClassBuilder ic = new ClassBuilder(new ToolBox(), "IC");
+// cb.addModifiers( "interface");
+// cb.addNestedClasses(ic);
+// System.out.println(cb.toString());
+// cb.write(Paths.get("src-out"));
+// }
+}
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java Thu Apr 26 17:59:02 2018 +0200
@@ -366,6 +366,10 @@
return new Result(opts, runWithArchive(opts));
}
+ public static Result run(CDSOptions opts) throws Exception {
+ return new Result(opts, runWithArchive(opts));
+ }
+
// Execute JVM with CDS archive, specify command line args suffix
public static OutputAnalyzer runWithArchive(String... cliPrefix)
throws Exception {
--- a/test/lib/jdk/test/lib/process/OutputAnalyzer.java Mon Apr 23 12:53:43 2018 +0200
+++ b/test/lib/jdk/test/lib/process/OutputAnalyzer.java Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -33,511 +33,525 @@
public final class OutputAnalyzer {
- private final String stdout;
- private final String stderr;
- private final int exitValue;
+ private final String stdout;
+ private final String stderr;
+ private final int exitValue;
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output and exit
+ * value from a Process
+ *
+ * @param process Process to analyze
+ * @throws IOException If an I/O error occurs.
+ */
+ public OutputAnalyzer(Process process) throws IOException {
+ OutputBuffer output = ProcessTools.getOutput(process);
+ exitValue = process.exitValue();
+ this.stdout = output.getStdout();
+ this.stderr = output.getStderr();
+ }
- /**
- * Create an OutputAnalyzer, a utility class for verifying output and exit
- * value from a Process
- *
- * @param process Process to analyze
- * @throws IOException If an I/O error occurs.
- */
- public OutputAnalyzer(Process process) throws IOException {
- OutputBuffer output = ProcessTools.getOutput(process);
- exitValue = process.exitValue();
- this.stdout = output.getStdout();
- this.stderr = output.getStderr();
- }
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output
+ *
+ * @param buf String buffer to analyze
+ */
+ public OutputAnalyzer(String buf) {
+ this(buf, buf);
+ }
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output
+ *
+ * @param stdout stdout buffer to analyze
+ * @param stderr stderr buffer to analyze
+ */
+ public OutputAnalyzer(String stdout, String stderr) {
+ this.stdout = stdout;
+ this.stderr = stderr;
+ exitValue = -1;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer is empty
+ *
+ * @throws RuntimeException
+ * If stdout was not empty
+ */
+ public void stdoutShouldBeEmpty() {
+ if (!getStdout().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was not empty");
+ }
+ }
- /**
- * Create an OutputAnalyzer, a utility class for verifying output
- *
- * @param buf String buffer to analyze
- */
- public OutputAnalyzer(String buf) {
- this(buf, buf);
- }
+ /**
+ * Verify that the stderr contents of output buffer is empty
+ *
+ * @throws RuntimeException
+ * If stderr was not empty
+ */
+ public void stderrShouldBeEmpty() {
+ if (!getStderr().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was not empty");
+ }
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer is empty,
+ * after filtering out the Hotspot warning messages
+ *
+ * @throws RuntimeException
+ * If stderr was not empty
+ */
+ public void stderrShouldBeEmptyIgnoreVMWarnings() {
+ if (!getStderr().replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was not empty");
+ }
+ }
- /**
- * Create an OutputAnalyzer, a utility class for verifying output
- *
- * @param stdout stdout buffer to analyze
- * @param stderr stderr buffer to analyze
- */
- public OutputAnalyzer(String stdout, String stderr) {
- this.stdout = stdout;
- this.stderr = stderr;
- exitValue = -1;
- }
+ /**
+ * Verify that the stdout contents of output buffer is not empty
+ *
+ * @throws RuntimeException
+ * If stdout was empty
+ */
+ public void stdoutShouldNotBeEmpty() {
+ if (getStdout().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was empty");
+ }
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer is not empty
+ *
+ * @throws RuntimeException
+ * If stderr was empty
+ */
+ public void stderrShouldNotBeEmpty() {
+ if (getStderr().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was empty");
+ }
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer shouldContain(String expectedString) {
+ if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
+ }
+ return this;
+ }
- /**
- * Verify that the stdout contents of output buffer is empty
- *
- * @throws RuntimeException
- * If stdout was not empty
- */
- public void stdoutShouldBeEmpty() {
- if (!getStdout().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stdout was not empty");
+ /**
+ * Verify that the stdout contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer stdoutShouldContain(String expectedString) {
+ if (!stdout.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
+ }
+ return this;
}
- }
+
+ /**
+ * Verify that the stderr contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer stderrShouldContain(String expectedString) {
+ if (!stderr.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
+ }
+ return this;
+ }
- /**
- * Verify that the stderr contents of output buffer is empty
- *
- * @throws RuntimeException
- * If stderr was not empty
- */
- public void stderrShouldBeEmpty() {
- if (!getStderr().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stderr was not empty");
+ /**
+ * Verify that the stdout and stderr contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer shouldNotContain(String notExpectedString) {
+ if (stdout.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+ }
+ if (stderr.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+ }
+ return this;
}
- }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer are empty
+ *
+ * @throws RuntimeException If the stdout and stderr are not empty
+ */
+ public OutputAnalyzer shouldBeEmpty() {
+ if (!stdout.isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was not empty");
+ }
+ if (!stderr.isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was not empty");
+ }
+ return this;
+ }
- /**
- * Verify that the stdout contents of output buffer is not empty
- *
- * @throws RuntimeException
- * If stdout was empty
- */
- public void stdoutShouldNotBeEmpty() {
- if (getStdout().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stdout was empty");
+ /**
+ * Verify that the stdout contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
+ if (stdout.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+ }
+ return this;
}
- }
+
+ /**
+ * Verify that the stderr contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
+ if (stderr.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+ }
+ return this;
+ }
- /**
- * Verify that the stderr contents of output buffer is not empty
- *
- * @throws RuntimeException
- * If stderr was empty
- */
- public void stderrShouldNotBeEmpty() {
- if (getStderr().isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stderr was empty");
+ /**
+ * Verify that the stdout and stderr contents of output buffer matches
+ * the pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer shouldMatch(String pattern) {
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (!stdoutMatcher.find() && !stderrMatcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stdout/stderr \n");
+ }
+ return this;
}
- }
+
+ /**
+ * Verify that the stdout contents of output buffer matches the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer stdoutShouldMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (!matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stdout \n");
+ }
+ return this;
+ }
/**
- * Verify that the stdout and stderr contents of output buffer contains the string
- *
- * @param expectedString String that buffer should contain
- * @throws RuntimeException If the string was not found
- */
- public OutputAnalyzer shouldContain(String expectedString) {
- if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout contents of output buffer contains the string
- *
- * @param expectedString String that buffer should contain
- * @throws RuntimeException If the string was not found
- */
- public OutputAnalyzer stdoutShouldContain(String expectedString) {
- if (!stdout.contains(expectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
- }
- return this;
- }
+ * Verify that the stderr contents of output buffer matches the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer stderrShouldMatch(String pattern) {
- /**
- * Verify that the stderr contents of output buffer contains the string
- *
- * @param expectedString String that buffer should contain
- * @throws RuntimeException If the string was not found
- */
- public OutputAnalyzer stderrShouldContain(String expectedString) {
- if (!stderr.contains(expectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (!matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stderr \n");
+ }
+ return this;
}
- return this;
- }
-
- /**
- * Verify that the stdout and stderr contents of output buffer does not contain the string
- *
- * @param expectedString String that the buffer should not contain
- * @throws RuntimeException If the string was found
- */
- public OutputAnalyzer shouldNotContain(String notExpectedString) {
- if (stdout.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
- }
- if (stderr.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
- }
- return this;
- }
- /**
- * Verify that the stdout and stderr contents of output buffer are empty
- *
- * @throws RuntimeException If the stdout and stderr are not empty
- */
- public OutputAnalyzer shouldBeEmpty() {
- if (!stdout.isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stdout was not empty");
- }
- if (!stderr.isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stderr was not empty");
+ /**
+ * Verify that the stdout and stderr contents of output buffer does not
+ * match the pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer shouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stdout: '" + matcher.group() + "' \n");
+ }
+ matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stderr: '" + matcher.group() + "' \n");
+ }
+ return this;
}
- return this;
- }
-
- /**
- * Verify that the stdout contents of output buffer does not contain the string
- *
- * @param expectedString String that the buffer should not contain
- * @throws RuntimeException If the string was found
- */
- public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
- if (stdout.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
- }
- return this;
- }
- /**
- * Verify that the stderr contents of output buffer does not contain the string
- *
- * @param expectedString String that the buffer should not contain
- * @throws RuntimeException If the string was found
- */
- public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
- if (stderr.contains(notExpectedString)) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+ /**
+ * Verify that the stdout contents of output buffer does not match the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stdout \n");
+ }
+ return this;
}
- return this;
- }
-
- /**
- * Verify that the stdout and stderr contents of output buffer matches
- * the pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was not found
- */
- public OutputAnalyzer shouldMatch(String pattern) {
- Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (!stdoutMatcher.find() && !stderrMatcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' missing from stdout/stderr \n");
- }
- return this;
- }
- /**
- * Verify that the stdout contents of output buffer matches the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was not found
- */
- public OutputAnalyzer stdoutShouldMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (!matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' missing from stdout \n");
- }
- return this;
- }
-
- /**
- * Verify that the stderr contents of output buffer matches the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was not found
- */
- public OutputAnalyzer stderrShouldMatch(String pattern) {
-
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (!matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' missing from stderr \n");
- }
- return this;
- }
+ /**
+ * Verify that the stderr contents of output buffer does not match the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer stderrShouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stderr \n");
+ }
+ return this;
+ }
- /**
- * Verify that the stdout and stderr contents of output buffer does not
- * match the pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was found
- */
- public OutputAnalyzer shouldNotMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stdout: '" + matcher.group() + "' \n");
- }
- matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stderr: '" + matcher.group() + "' \n");
- }
- return this;
- }
-
- /**
- * Verify that the stdout contents of output buffer does not match the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was found
- */
- public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stdout \n");
- }
- return this;
- }
+ /**
+ * Get the captured group of the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @param group The group to capture
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern, int group) {
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (stderrMatcher.find()) {
+ return stderrMatcher.group(group);
+ }
+ if (stdoutMatcher.find()) {
+ return stdoutMatcher.group(group);
+ }
+ return null;
+ }
- /**
- * Verify that the stderr contents of output buffer does not match the
- * pattern
- *
- * @param pattern
- * @throws RuntimeException If the pattern was found
- */
- public OutputAnalyzer stderrShouldNotMatch(String pattern) {
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' found in stderr \n");
- }
- return this;
- }
-
- /**
- * Get the captured group of the first string matching the pattern.
- * stderr is searched before stdout.
- *
- * @param pattern The multi-line pattern to match
- * @param group The group to capture
- * @return The matched string or null if no match was found
- */
- public String firstMatch(String pattern, int group) {
- Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
- if (stderrMatcher.find()) {
- return stderrMatcher.group(group);
+ /**
+ * Get the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern) {
+ return firstMatch(pattern, 0);
}
- if (stdoutMatcher.find()) {
- return stdoutMatcher.group(group);
- }
- return null;
- }
- /**
- * Get the first string matching the pattern.
- * stderr is searched before stdout.
- *
- * @param pattern The multi-line pattern to match
- * @return The matched string or null if no match was found
- */
- public String firstMatch(String pattern) {
- return firstMatch(pattern, 0);
- }
+ /**
+ * Verify the exit value of the process
+ *
+ * @param expectedExitValue Expected exit value from process
+ * @throws RuntimeException If the exit value from the process did not match the expected value
+ */
+ public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
+ if (getExitValue() != expectedExitValue) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("Expected to get exit value of ["
+ + expectedExitValue + "]\n");
+ }
+ return this;
+ }
- /**
- * Verify the exit value of the process
- *
- * @param expectedExitValue Expected exit value from process
- * @throws RuntimeException If the exit value from the process did not match the expected value
- */
- public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
- if (getExitValue() != expectedExitValue) {
- reportDiagnosticSummary();
- throw new RuntimeException("Expected to get exit value of ["
- + expectedExitValue + "]\n");
- }
- return this;
- }
-
- /**
- * Verify the exit value of the process
- *
- * @param notExpectedExitValue Unexpected exit value from process
- * @throws RuntimeException If the exit value from the process did match the expected value
- */
- public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) {
- if (getExitValue() == notExpectedExitValue) {
- reportDiagnosticSummary();
- throw new RuntimeException("Unexpected to get exit value of ["
- + notExpectedExitValue + "]\n");
- }
- return this;
- }
+ /**
+ * Verify the exit value of the process
+ *
+ * @param notExpectedExitValue Unexpected exit value from process
+ * @throws RuntimeException If the exit value from the process did match the expected value
+ */
+ public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) {
+ if (getExitValue() == notExpectedExitValue) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("Unexpected to get exit value of ["
+ + notExpectedExitValue + "]\n");
+ }
+ return this;
+ }
- /**
- * Report summary that will help to diagnose the problem
- * Currently includes:
- * - standard input produced by the process under test
- * - standard output
- * - exit code
- * Note: the command line is printed by the ProcessTools
- */
- public void reportDiagnosticSummary() {
- String msg =
- " stdout: [" + stdout + "];\n" +
- " stderr: [" + stderr + "]\n" +
- " exitValue = " + getExitValue() + "\n";
+ /**
+ * Report summary that will help to diagnose the problem
+ * Currently includes:
+ * - standard input produced by the process under test
+ * - standard output
+ * - exit code
+ * Note: the command line is printed by the ProcessTools
+ */
+ public void reportDiagnosticSummary() {
+ String msg =
+ " stdout: [" + stdout + "];\n" +
+ " stderr: [" + stderr + "]\n" +
+ " exitValue = " + getExitValue() + "\n";
- System.err.println(msg);
- }
+ System.err.println(msg);
+ }
- /**
- * Print the stdout buffer to the given {@code PrintStream}.
- *
- * @return this OutputAnalyzer
- */
- public OutputAnalyzer outputTo(PrintStream out) {
- out.println(getStdout());
- return this;
- }
+ /**
+ * Print the stdout buffer to the given {@code PrintStream}.
+ *
+ * @return this OutputAnalyzer
+ */
+ public OutputAnalyzer outputTo(PrintStream out) {
+ out.println(getStdout());
+ return this;
+ }
- /**
- * Print the stderr buffer to the given {@code PrintStream}.
- *
- * @return this OutputAnalyzer
- */
- public OutputAnalyzer errorTo(PrintStream out) {
- out.println(getStderr());
- return this;
- }
+ /**
+ * Print the stderr buffer to the given {@code PrintStream}.
+ *
+ * @return this OutputAnalyzer
+ */
+ public OutputAnalyzer errorTo(PrintStream out) {
+ out.println(getStderr());
+ return this;
+ }
- /**
- * Get the contents of the output buffer (stdout and stderr)
- *
- * @return Content of the output buffer
- */
- public String getOutput() {
- return stdout + stderr;
- }
+ /**
+ * Get the contents of the output buffer (stdout and stderr)
+ *
+ * @return Content of the output buffer
+ */
+ public String getOutput() {
+ return stdout + stderr;
+ }
- /**
- * Get the contents of the stdout buffer
- *
- * @return Content of the stdout buffer
- */
- public String getStdout() {
- return stdout;
- }
+ /**
+ * Get the contents of the stdout buffer
+ *
+ * @return Content of the stdout buffer
+ */
+ public String getStdout() {
+ return stdout;
+ }
- /**
- * Get the contents of the stderr buffer
- *
- * @return Content of the stderr buffer
- */
- public String getStderr() {
- return stderr;
- }
+ /**
+ * Get the contents of the stderr buffer
+ *
+ * @return Content of the stderr buffer
+ */
+ public String getStderr() {
+ return stderr;
+ }
- /**
- * Get the process exit value
- *
- * @return Process exit value
- */
- public int getExitValue() {
- return exitValue;
- }
+ /**
+ * Get the process exit value
+ *
+ * @return Process exit value
+ */
+ public int getExitValue() {
+ return exitValue;
+ }
- /**
- * Get the contents of the output buffer (stdout and stderr) as list of strings.
- * Output will be split by newlines.
- *
- * @return Contents of the output buffer as list of strings
- */
- public List<String> asLines() {
- return asLines(getOutput());
- }
+ /**
+ * Get the contents of the output buffer (stdout and stderr) as list of strings.
+ * Output will be split by newlines.
+ *
+ * @return Contents of the output buffer as list of strings
+ */
+ public List<String> asLines() {
+ return asLines(getOutput());
+ }
- private List<String> asLines(String buffer) {
- return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
- }
+ private List<String> asLines(String buffer) {
+ return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
+ }
- private static final String jvmwarningmsg = ".* VM warning:.*";
+ private static final String jvmwarningmsg = ".* VM warning:.*";
- /**
- * Verifies that the stdout and stderr contents of output buffer are empty, after
- * filtering out the HotSpot warning messages.
- *
- * @throws RuntimeException If the stdout and stderr are not empty
- */
- public OutputAnalyzer shouldBeEmptyIgnoreVMWarnings() {
- if (!stdout.isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stdout was not empty");
+ /**
+ * Verifies that the stdout and stderr contents of output buffer are empty, after
+ * filtering out the HotSpot warning messages.
+ *
+ * @throws RuntimeException If the stdout and stderr are not empty
+ */
+ public OutputAnalyzer shouldBeEmptyIgnoreVMWarnings() {
+ if (!stdout.isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was not empty");
+ }
+ if (!stderr.replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was not empty");
+ }
+ return this;
}
- if (!stderr.replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {
- reportDiagnosticSummary();
- throw new RuntimeException("stderr was not empty");
- }
- return this;
- }
- /**
- * Verify that the stderr contents of output buffer matches the pattern,
- * after filtering out the Hotespot warning messages
- *
- * @param pattern
- * @throws RuntimeException If the pattern was not found
- */
- public OutputAnalyzer stderrShouldMatchIgnoreVMWarnings(String pattern) {
- String stderr = this.stderr.replaceAll(jvmwarningmsg + "\\R", "");
- Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
- if (!matcher.find()) {
- reportDiagnosticSummary();
- throw new RuntimeException("'" + pattern
- + "' missing from stderr \n");
- }
- return this;
- }
+ /**
+ * Verify that the stderr contents of output buffer matches the pattern,
+ * after filtering out the Hotespot warning messages
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer stderrShouldMatchIgnoreVMWarnings(String pattern) {
+ String stderr = this.stderr.replaceAll(jvmwarningmsg + "\\R", "");
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (!matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stderr \n");
+ }
+ return this;
+ }
- /**
- * Returns the contents of the output buffer (stdout and stderr), without those
- * JVM warning msgs, as list of strings. Output is split by newlines.
- *
- * @return Contents of the output buffer as list of strings
- */
- public List<String> asLinesWithoutVMWarnings() {
- return Arrays.asList(getOutput().split("\\R"))
- .stream()
- .filter(Pattern.compile(jvmwarningmsg).asPredicate().negate())
- .collect(Collectors.toList());
- }
+ /**
+ * Returns the contents of the output buffer (stdout and stderr), without those
+ * JVM warning msgs, as list of strings. Output is split by newlines.
+ *
+ * @return Contents of the output buffer as list of strings
+ */
+ public List<String> asLinesWithoutVMWarnings() {
+ return Arrays.asList(getOutput().split("\\R"))
+ .stream()
+ .filter(Pattern.compile(jvmwarningmsg).asPredicate().negate())
+ .collect(Collectors.toList());
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/JDK-8201466.js Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8201466: Nashorn: defineProperty setters/getters on prototype object ignored with numeric property names
+ *
+ * @test
+ * @run
+ */
+
+var z = {}, s = null, g = null;
+
+Object.defineProperty(z,'0', {
+ get:function(){ g = 2; return 1;},
+ set:function(v){ s = v;}
+});
+
+var x = Object.create(z);
+x[0] = 3;
+
+Assert.assertTrue(x[0] === 1);
+Assert.assertTrue(g === 2);
+Assert.assertTrue(s === 3);
+