diff --git a/hotspot/make/CompileTools.gmk b/hotspot/make/CompileTools.gmk index c80632226cf..309d9c9aaf6 100644 --- a/hotspot/make/CompileTools.gmk +++ b/hotspot/make/CompileTools.gmk @@ -47,11 +47,10 @@ ifeq ($(INCLUDE_GRAAL), true) $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.common/src \ + $(SRC_DIR)/org.graalvm.word/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 \ - $(SRC_DIR)/org.graalvm.compiler.api.collections/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.asm/src \ $(SRC_DIR)/org.graalvm.compiler.bytecode/src \ @@ -68,6 +67,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.phases.common/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ $(SRC_DIR)/org.graalvm.compiler.virtual/src \ + $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ @@ -102,6 +102,7 @@ ifeq ($(INCLUDE_GRAAL), true) SRC := \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.options.processor/src \ + $(SRC_DIR)/org.graalvm.util/src \ , \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor, \ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor.jar, \ @@ -114,9 +115,8 @@ ifeq ($(INCLUDE_GRAAL), true) $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.common/src \ + $(SRC_DIR)/org.graalvm.word/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \ - $(SRC_DIR)/org.graalvm.compiler.api.collections/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.code/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \ @@ -125,6 +125,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ + $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ diff --git a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk index a8e60309b1c..623430abab6 100644 --- a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk +++ b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk @@ -37,7 +37,6 @@ SRC_DIR := $(HOTSPOT_TOPDIR)/src/$(MODULE)/share/classes PROC_SRC_SUBDIRS := \ org.graalvm.compiler.code \ - org.graalvm.compiler.common \ org.graalvm.compiler.core \ org.graalvm.compiler.core.aarch64 \ org.graalvm.compiler.core.amd64 \ diff --git a/hotspot/make/lib/CompileDtracePostJvm.gmk b/hotspot/make/lib/CompileDtracePostJvm.gmk index 77a4e30f4d9..1051cafe8dd 100644 --- a/hotspot/make/lib/CompileDtracePostJvm.gmk +++ b/hotspot/make/lib/CompileDtracePostJvm.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -52,7 +52,7 @@ ifeq ($(call check-jvm-feature, dtrace), true) CXX := $(BUILD_CXX), \ LDEXE := $(BUILD_CXX), \ generateJvmOffsets.cpp_CXXFLAGS := $(JVM_CFLAGS) -mt -xnolib -norunpath, \ - generateJvmOffsetsMain.c_CFLAGS := -library=%none -mt -m64 -norunpath -z nodefs, \ + generateJvmOffsetsMain.c_CFLAGS := -mt -m64 -norunpath -z nodefs, \ LDFLAGS := -m64, \ LIBS := -lc, \ OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ diff --git a/hotspot/make/lib/Lib-jdk.aot.gmk b/hotspot/make/lib/Lib-jdk.aot.gmk deleted file mode 100644 index d799fa45286..00000000000 --- a/hotspot/make/lib/Lib-jdk.aot.gmk +++ /dev/null @@ -1,53 +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. 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 $(SPEC) -include NativeCompilation.gmk - -$(eval $(call IncludeCustomExtension, hotspot, lib/Lib-jdk.aot.gmk)) - -############################################################################## -# Build libjelfshim only when AOT is enabled. -ifeq ($(ENABLE_AOT), true) - JELFSHIM_NAME := jelfshim - - $(eval $(call SetupNativeCompilation, BUILD_LIBJELFSHIM, \ - TOOLCHAIN := TOOLCHAIN_DEFAULT, \ - OPTIMIZATION := LOW, \ - LIBRARY := $(JELFSHIM_NAME), \ - OUTPUT_DIR := $(call FindLibDirForModule, $(MODULE)), \ - SRC := $(HOTSPOT_TOPDIR)/src/jdk.aot/unix/native/libjelfshim, \ - CFLAGS := $(CFLAGS_JDKLIB) $(ELF_CFLAGS) \ - -DAOT_VERSION_STRING='"$(VERSION_STRING)"' \ - -I$(SUPPORT_OUTPUTDIR)/headers/$(MODULE), \ - LDFLAGS := $(LDFLAGS_JDKLIB), \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lib$(JELFSHIM_NAME), \ - LIBS := $(ELF_LIBS) $(LIBS_JDKLIB), \ - )) - - TARGETS += $(BUILD_LIBJELFSHIM) -endif - -############################################################################## diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index 42eb76af57e..01ac33a605c 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -35,12 +35,16 @@ include $(SPEC) include MakeBase.gmk include TestFilesCompilation.gmk +$(eval $(call IncludeCustomExtension, hotspot, test/JtregNative.gmk)) + ################################################################################ # Targets for building the native tests themselves. ################################################################################ # Add more directories here when needed. -BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ +BUILD_HOTSPOT_JTREG_NATIVE_SRC += \ + $(HOTSPOT_TOPDIR)/test/gc/g1/TestJNIWeakG1 \ + $(HOTSPOT_TOPDIR)/test/gc/stress/gclocker \ $(HOTSPOT_TOPDIR)/test/native_sanity \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \ @@ -53,6 +57,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \ $(HOTSPOT_TOPDIR)/test/runtime/SameObject \ $(HOTSPOT_TOPDIR)/test/runtime/BoolReturn \ + $(HOTSPOT_TOPDIR)/test/runtime/noClassDefFoundMsg \ $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \ $(HOTSPOT_TOPDIR)/test/compiler/calls \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \ @@ -65,6 +70,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart \ + $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/StartPhase/AllowedFunctions \ # # Add conditional directories here when needed. @@ -91,6 +97,7 @@ ifeq ($(TOOLCHAIN_TYPE), solstudio) BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassFileLoadHook := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassLoadPrepare := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAThreadStart := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libAllowedFunctions := -lc endif ifeq ($(OPENJDK_TARGET_OS), linux) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index cf3fd216364..246ba240ebc 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, Red Hat Inc. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -3564,7 +3564,7 @@ const int Matcher::min_vector_size(const BasicType bt) { } // Vector ideal reg. -const int Matcher::vector_ideal_reg(int len) { +const uint Matcher::vector_ideal_reg(int len) { switch(len) { case 8: return Op_VecD; case 16: return Op_VecX; @@ -3573,7 +3573,7 @@ const int Matcher::vector_ideal_reg(int len) { return 0; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { return Op_VecX; } @@ -5423,6 +5423,16 @@ operand immI_56() interface(CONST_INTER); %} +operand immI_63() +%{ + predicate(n->get_int() == 63); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + operand immI_64() %{ predicate(n->get_int() == 64); @@ -5453,20 +5463,10 @@ operand immI_65535() interface(CONST_INTER); %} -operand immL_63() -%{ - predicate(n->get_int() == 63); - match(ConI); - - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - operand immL_255() %{ - predicate(n->get_int() == 255); - match(ConI); + predicate(n->get_long() == 255L); + match(ConL); op_cost(0); format %{ %} @@ -11146,7 +11146,7 @@ instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{ ins_pipe(ldiv_reg_reg); %} -instruct signExtractL(iRegLNoSp dst, iRegL src1, immL_63 div1, immL_63 div2) %{ +instruct signExtractL(iRegLNoSp dst, iRegL src1, immI_63 div1, immI_63 div2) %{ match(Set dst (URShiftL (RShiftL src1 div1) div2)); ins_cost(INSN_COST); format %{ "lsr $dst, $src1, $div1" %} @@ -11156,7 +11156,7 @@ instruct signExtractL(iRegLNoSp dst, iRegL src1, immL_63 div1, immL_63 div2) %{ ins_pipe(ialu_reg_shift); %} -instruct div2RoundL(iRegLNoSp dst, iRegL src, immL_63 div1, immL_63 div2) %{ +instruct div2RoundL(iRegLNoSp dst, iRegL src, immI_63 div1, immI_63 div2) %{ match(Set dst (AddL src (URShiftL (RShiftL src div1) div2))); ins_cost(INSN_COST); format %{ "add $dst, $src, $div1" %} @@ -15387,9 +15387,9 @@ instruct ShouldNotReachHere() %{ format %{ "ShouldNotReachHere" %} ins_encode %{ - // TODO - // implement proper trap call here - __ brk(999); + // +1 so NativeInstruction::is_sigill_zombie_not_entrant() doesn't + // return true + __ dpcs1(0xdead + 1); %} ins_pipe(pipe_class_default); diff --git a/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp index adb30aa0d1d..49a266e5480 100644 --- a/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp @@ -109,9 +109,15 @@ int AbstractInterpreter::size_activation(int max_stack, // for the callee's params we only need to account for the extra // locals. int size = overhead + - (callee_locals - callee_params)*Interpreter::stackElementWords + + (callee_locals - callee_params) + monitors * frame::interpreter_frame_monitor_size() + - temps* Interpreter::stackElementWords + extra_args; + // On the top frame, at all times SP <= ESP, and SP is + // 16-aligned. We ensure this by adjusting SP on method + // entry and re-entry to allow room for the maximum size of + // the expression stack. When we call another method we bump + // SP so that no stack space is wasted. So, only on the top + // frame do we need to allow max_stack words. + (is_top_frame ? max_stack : temps + extra_args); // On AArch64 we always keep the stack pointer 16-aligned, so we // must round up here. diff --git a/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp index fc7890e945b..701d3af7fc0 100644 --- a/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp @@ -30,12 +30,6 @@ class Bytes: AllStatic { public: - // Returns true if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. For example, this is true for Intel x86, but false for Solaris - // on Sparc. - static inline bool is_Java_byte_ordering_different(){ return true; } - - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering // (no special code is needed since x86 CPUs can access unaligned data) static inline u2 get_native_u2(address p) { return *(u2*)p; } diff --git a/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp index 2db73cd1523..3e213003947 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -23,12 +23,6 @@ * */ -#include "precompiled.hpp" -#include "c1/c1_FpuStackSim.hpp" -#include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" -#include "utilities/ostream.hpp" - //-------------------------------------------------------- // FpuStackSim //-------------------------------------------------------- diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp index 0016aa9ba6a..e6d9de99685 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -2740,8 +2740,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { // set already but no need to check. __ cbz(rscratch1, next); - __ andr(rscratch1, tmp, TypeEntries::type_unknown); - __ cbnz(rscratch1, next); // already unknown. Nothing to do anymore. + __ tbnz(tmp, exact_log2(TypeEntries::type_unknown), next); // already unknown. Nothing to do anymore. if (TypeEntries::is_type_none(current_klass)) { __ cbz(rscratch2, none); @@ -2761,8 +2760,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "conflict only"); __ ldr(tmp, mdo_addr); - __ andr(rscratch1, tmp, TypeEntries::type_unknown); - __ cbnz(rscratch1, next); // already unknown. Nothing to do anymore. + __ tbnz(tmp, exact_log2(TypeEntries::type_unknown), next); // already unknown. Nothing to do anymore. } // different than before. Cannot keep accurate profile. @@ -2812,8 +2810,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent"); __ ldr(tmp, mdo_addr); - __ andr(rscratch1, tmp, TypeEntries::type_unknown); - __ cbnz(rscratch1, next); // already unknown. Nothing to do anymore. + __ tbnz(tmp, exact_log2(TypeEntries::type_unknown), next); // already unknown. Nothing to do anymore. __ orr(tmp, tmp, TypeEntries::type_unknown); __ str(tmp, mdo_addr); diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp index 81636fb8ea1..480a6435f3d 100644 --- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -270,7 +270,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( get_constant_pool(result); // load pointer for resolved_references[] objArray - ldr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes())); + ldr(result, Address(result, ConstantPool::cache_offset_in_bytes())); + ldr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes())); // JNIHandles::resolve(obj); ldr(result, Address(result, 0)); // Add in the index @@ -278,6 +279,15 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } +void InterpreterMacroAssembler::load_resolved_klass_at_offset( + Register cpool, Register index, Register klass, Register temp) { + add(temp, cpool, index, LSL, LogBytesPerWord); + ldrh(temp, Address(temp, sizeof(ConstantPool))); // temp = resolved_klass_index + ldr(klass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // klass = cpool->_resolved_klasses + add(klass, klass, temp, LSL, LogBytesPerWord); + ldr(klass, Address(klass, Array::base_offset_in_bytes())); +} + // Generate a subtype check: branch to ok_is_subtype if sub_klass is a // subtype of super_klass. // @@ -682,7 +692,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) } // Load (object->mark() | 1) into swap_reg - ldr(rscratch1, Address(obj_reg, 0)); + ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); orr(swap_reg, rscratch1, 1); // Save (object->mark() | 1) into BasicLock's displaced header @@ -694,14 +704,14 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) Label fail; if (PrintBiasedLockingStatistics) { Label fast; - cmpxchgptr(swap_reg, lock_reg, obj_reg, rscratch1, fast, &fail); + cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, rscratch1, fast, &fail); bind(fast); atomic_incw(Address((address)BiasedLocking::fast_path_entry_count_addr()), rscratch2, rscratch1, tmp); b(done); bind(fail); } else { - cmpxchgptr(swap_reg, lock_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); + cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); } // Test if the oopMark is an obvious stack pointer, i.e., @@ -791,7 +801,7 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) cbz(header_reg, done); // Atomic swap back the old header - cmpxchgptr(swap_reg, header_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); + cmpxchg_obj_header(swap_reg, header_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); // Call the runtime routine for slow case. str(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); // restore obj @@ -1744,8 +1754,7 @@ void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register t // Load the offset of the area within the MDO used for // parameters. If it's negative we're not profiling any parameters ldr(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()))); - cmp(tmp1, 0u); - br(Assembler::LT, profile_continue); + tbnz(tmp1, 63, profile_continue); // i.e. sign bit set // Compute a pointer to the area for parameters from the offset // and move the pointer to the slot for the last diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp index 925690b0d80..637ae481f5b 100644 --- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -54,9 +54,6 @@ class InterpreterMacroAssembler: public MacroAssembler { int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table, bool verifyoop = true); @@ -67,6 +64,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void jump_to_entry(address entry); + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Interpreter-specific registers void save_bcp() { str(rbcp, Address(rfp, frame::interpreter_frame_bcp_offset * wordSize)); @@ -123,6 +123,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // load cpool->resolved_references(index); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index); + void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp); + void pop_ptr(Register r = r0); void pop_i(Register r = r0); void pop_l(Register r = r0); diff --git a/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp index a09c5230dc4..b0f9acee633 100644 --- a/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp @@ -76,8 +76,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { SafepointSynchronize::safepoint_counter_addr(), offset); Address safepoint_counter_addr(rcounter_addr, offset); __ ldrw(rcounter, safepoint_counter_addr); - __ andw(rscratch1, rcounter, 1); - __ cbnzw(rscratch1, slow); + __ tbnz(rcounter, 0, slow); __ eor(robj, c_rarg1, rcounter); __ eor(robj, robj, rcounter); // obj, since // robj ^ rcounter ^ rcounter == robj diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp index f9cc50fe4d0..bebd5ae8ca9 100644 --- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -55,7 +55,7 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) } } #endif // ASSERT - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); MacroAssembler::patch_oop(pc, (address)obj()); int oop_index = _oop_recorder->find_index(value); diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index 303c2f5eb8e..bd4433dd6b9 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -515,7 +515,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, mov(rscratch1, markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); andr(swap_reg, swap_reg, rscratch1); orr(tmp_reg, swap_reg, rthread); - cmpxchgptr(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); + cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); // If the biasing toward our thread failed, this means that // another thread succeeded in biasing it toward itself and we // need to revoke that bias. The revocation will occur in the @@ -542,7 +542,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Label here; load_prototype_header(tmp_reg, obj_reg); orr(tmp_reg, rthread, tmp_reg); - cmpxchgptr(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); + cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); // If the biasing toward our thread failed, then another thread // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. @@ -569,7 +569,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, { Label here, nope; load_prototype_header(tmp_reg, obj_reg); - cmpxchgptr(swap_reg, tmp_reg, obj_reg, rscratch1, here, &nope); + cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, rscratch1, here, &nope); bind(here); // Fall through to the normal CAS-based lock, because no matter what @@ -2141,6 +2141,12 @@ void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Reg b(*fail); } +void MacroAssembler::cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, + Label &succeed, Label *fail) { + assert(oopDesc::mark_offset_in_bytes() == 0, "assumption"); + cmpxchgptr(oldv, newv, obj, tmp, succeed, fail); +} + void MacroAssembler::cmpxchgw(Register oldv, Register newv, Register addr, Register tmp, Label &succeed, Label *fail) { // oldv holds comparison value diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index 59171e5dd19..5e72babc57e 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -77,12 +77,6 @@ class MacroAssembler: public Assembler { bool check_exceptions // whether to check for pending exceptions after return ); - // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); // Maximum size of class area in Metaspace when compressed @@ -97,6 +91,12 @@ class MacroAssembler: public Assembler { > (1u << log2_intptr(CompressedClassSpaceSize)))); } + // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles PopFrame and ForceEarlyReturn requests. + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Biased locking support // lock_reg and obj_reg must be loaded up with the appropriate values. // swap_reg is killed. @@ -974,6 +974,8 @@ public: // Various forms of CAS + void cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, + Label &suceed, Label *fail); void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, Label &suceed, Label *fail); diff --git a/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp deleted file mode 100644 index 72af9a84f04..00000000000 --- a/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 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. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -extern "C" { - void aarch64_prolog(void); -} - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - -#ifdef BUILTIN_SIM - // Write a dummy word to the writable shared metaspace. - // MetaspaceShared::initialize_shared_spaces will fill it with the - // address of aarch64_prolog(). - address *prolog_ptr = (address*)*md_top; - *(intptr_t *)(*md_top) = (intptr_t)0; - (*md_top) += sizeof(intptr_t); -#endif - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // We're called directly from C code. -#ifdef BUILTIN_SIM - __ c_stub_prolog(8, 0, MacroAssembler::ret_type_integral, prolog_ptr); -#endif - // Load rscratch1 with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - __ mov(rscratch1, (i << 8) + j); - __ b(common_code); - } - } - - __ bind(common_code); - - Register tmp0 = r10, tmp1 = r11; // AAPCS64 temporary registers - __ enter(); - __ lsr(tmp0, rscratch1, 8); // isolate vtable identifier. - __ mov(tmp1, (address)vtbl_list); // address of list of vtable pointers. - __ ldr(tmp1, Address(tmp1, tmp0, Address::lsl(LogBytesPerWord))); // get correct vtable pointer. - __ str(tmp1, Address(c_rarg0)); // update vtable pointer in obj. - __ add(rscratch1, tmp1, rscratch1, ext::uxtb, LogBytesPerWord); // address of real method pointer. - __ ldr(rscratch1, Address(rscratch1)); // get real method pointer. - __ blrt(rscratch1, 8, 0, 1); // jump to the real method. - __ leave(); - __ ret(lr); - - *mc_top = (char*)__ pc(); -} - -#ifdef BUILTIN_SIM -void MetaspaceShared::relocate_vtbl_list(char **buffer) { - void **sim_entry = (void**)*buffer; - *sim_entry = (void*)aarch64_prolog; - *buffer += sizeof(intptr_t); -} -#endif diff --git a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp index dedabb6729b..cc837ee83af 100644 --- a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -63,7 +63,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Register temp = rscratch2; Register temp2 = rscratch1; // used by MacroAssembler::cmpptr Label L_ok, L_bad; @@ -137,8 +137,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(method_temp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ ldr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(method_temp); + __ ldr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -282,7 +283,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method( rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -335,14 +337,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ ldr(rmethod, member_vmtarget); + __ load_heap_oop(rmethod, member_vmtarget); + __ ldr(rmethod, vmtarget_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ ldr(rmethod, member_vmtarget); + __ load_heap_oop(rmethod, member_vmtarget); + __ ldr(rmethod, vmtarget_method); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp index a286102e7b1..872ffc7efe7 100644 --- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -1842,7 +1842,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, } // Load (object->mark() | 1) into swap_reg %r0 - __ ldr(rscratch1, Address(obj_reg, 0)); + __ ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ orr(swap_reg, rscratch1, 1); // Save (object->mark() | 1) into BasicLock's displaced header @@ -1850,7 +1850,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // src -> dest iff dest == r0 else r0 <- dest { Label here; - __ cmpxchgptr(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); + __ cmpxchg_obj_header(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); } // Hmm should this move to the slow path code area??? @@ -2029,7 +2029,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Atomic swap old header if oop still contains the stack lock Label succeed; - __ cmpxchgptr(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); + __ cmpxchg_obj_header(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); __ bind(succeed); // slow path re-enters here diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp index 6f44292c55a..f22f8d874aa 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -402,14 +402,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common( return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - // NULL last_sp until next java call - __ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ dispatch_next(state); - return entry; -} - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -444,6 +436,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ notify(Assembler::method_reentry); } #endif + + __ check_and_handle_popframe(rthread); + __ check_and_handle_earlyret(rthread); + __ get_dispatch(); __ dispatch_next(state, step); diff --git a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp index f0f0f5a6ee5..e110035d31a 100644 --- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -246,8 +246,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, assert(load_bc_into_bc_reg, "we use bc_reg as temp"); __ get_cache_and_index_and_bytecode_at_bcp(temp_reg, bc_reg, temp_reg, byte_no, 1); __ movw(bc_reg, bc); - __ cmpw(temp_reg, (unsigned) 0); - __ br(Assembler::EQ, L_patch_done); // don't patch + __ cbzw(temp_reg, L_patch_done); // don't patch } break; default: @@ -3418,8 +3417,7 @@ void TemplateTable::_new() { __ br(Assembler::NE, slow_case); // get InstanceKlass - __ lea(r4, Address(r4, r3, Address::lsl(3))); - __ ldr(r4, Address(r4, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(r4, r3, r4, rscratch1); // make sure klass is initialized & doesn't have finalizer // make sure klass is fully initialized @@ -3572,8 +3570,7 @@ void TemplateTable::checkcast() // Get superklass in r0 and subklass in r3 __ bind(quicked); __ mov(r3, r0); // Save object in r3; r0 needed for subtype check - __ lea(r0, Address(r2, r19, Address::lsl(3))); - __ ldr(r0, Address(r0, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(r2, r19, r0, rscratch1); // r0 = klass __ bind(resolved); __ load_klass(r19, r3); @@ -3629,8 +3626,7 @@ void TemplateTable::instanceof() { // Get superklass in r0 and subklass in r3 __ bind(quicked); __ load_klass(r3, r0); - __ lea(r0, Address(r2, r19, Address::lsl(3))); - __ ldr(r0, Address(r0, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(r2, r19, r0, rscratch1); __ bind(resolved); diff --git a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp index 223f1810a6f..9301f687169 100644 --- a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp @@ -51,6 +51,11 @@ extern "C" void bad_compiled_vtable_index(JavaThread* thread, VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { const int aarch64_code_length = VtableStub::pd_code_size_limit(true); VtableStub* s = new(aarch64_code_length) VtableStub(true, vtable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), aarch64_code_length); MacroAssembler* masm = new MacroAssembler(&cb); diff --git a/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp b/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp index 7899c102e5b..35f0d258e49 100644 --- a/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp +++ b/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -234,8 +234,15 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef AARCH64 interpreter_frame->interpreter_frame_set_stack_top(stack_top); + // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots, + // none of which are at the same time, so we just need to make sure there is enough room + // for the biggest user: + // -reserved slot for exception handler + // -reserved slots for JSR292. Method::extra_stack_entries() is the size. + // -3 reserved slots so get_method_counters() can save some registers before call_VM(). + int max_stack = method->constMethod()->max_stack() + MAX2(3, Method::extra_stack_entries()); intptr_t* extended_sp = (intptr_t*) monbot - - (method->max_stack() + 1) * Interpreter::stackElementWords - // +1 is reserved slot for exception handler + (max_stack * Interpreter::stackElementWords) - popframe_extra_args; extended_sp = (intptr_t*)round_down((intptr_t)extended_sp, StackAlignmentInBytes); interpreter_frame->interpreter_frame_set_extended_sp(extended_sp); diff --git a/hotspot/src/cpu/arm/vm/arm.ad b/hotspot/src/cpu/arm/vm/arm.ad index ef84124ef43..ff1ef67390c 100644 --- a/hotspot/src/cpu/arm/vm/arm.ad +++ b/hotspot/src/cpu/arm/vm/arm.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2008, 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 @@ -1122,7 +1122,7 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg corresponding to specified size in bytes -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize >= size, ""); switch(size) { case 8: return Op_VecD; @@ -1132,7 +1132,7 @@ const int Matcher::vector_ideal_reg(int size) { return 0; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { return vector_ideal_reg(size); } @@ -11752,9 +11752,13 @@ instruct ShouldNotReachHere( ) size(4); // Use the following format syntax - format %{ "breakpoint ; ShouldNotReachHere" %} + format %{ "ShouldNotReachHere" %} ins_encode %{ - __ breakpoint(); +#ifdef AARCH64 + __ dpcs1(0xdead); +#else + __ udf(0xdead); +#endif %} ins_pipe(tail_call); %} diff --git a/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp b/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp index e32f6a98f29..95e6568832e 100644 --- a/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp +++ b/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp @@ -578,6 +578,11 @@ class Assembler : public AbstractAssembler { F(bl, 0xb) #undef F + void udf(int imm_16) { + assert((imm_16 >> 16) == 0, "encoding constraint"); + emit_int32(0xe7f000f0 | (imm_16 & 0xfff0) << 8 | (imm_16 & 0xf)); + } + // ARMv7 instructions #define F(mnemonic, wt) \ diff --git a/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp b/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp index 44d0504036c..9c6cd14c3f8 100644 --- a/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp +++ b/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp @@ -1083,6 +1083,7 @@ class Assembler : public AbstractAssembler { F(brk, 0b001, 0b000, 0b00) F(hlt, 0b010, 0b000, 0b00) + F(dpcs1, 0b101, 0b000, 0b01) #undef F enum SystemRegister { // o0<1> op1<3> CRn<4> CRm<4> op2<3> diff --git a/hotspot/src/cpu/arm/vm/bytes_arm.hpp b/hotspot/src/cpu/arm/vm/bytes_arm.hpp index 0cf7e2a77c9..0e5a894050a 100644 --- a/hotspot/src/cpu/arm/vm/bytes_arm.hpp +++ b/hotspot/src/cpu/arm/vm/bytes_arm.hpp @@ -35,12 +35,6 @@ class Bytes: AllStatic { public: - // Returns true if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. - static inline bool is_Java_byte_ordering_different() { - return VM_LITTLE_ENDIAN != 0; - } - static inline u2 get_Java_u2(address p) { return (u2(p[0]) << 8) | u2(p[1]); } diff --git a/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp b/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp index ac826b491a2..287f4e412d7 100644 --- a/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp +++ b/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -22,10 +22,4 @@ * */ -#include "precompiled.hpp" -#include "c1/c1_FpuStackSim.hpp" -#include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" -#include "utilities/ostream.hpp" - // Nothing needed here diff --git a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp index 96df37c275e..364ce6e854c 100644 --- a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp +++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp @@ -298,7 +298,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( Register cache = result; // load pointer for resolved_references[] objArray - ldr(cache, Address(result, ConstantPool::resolved_references_offset_in_bytes())); + ldr(cache, Address(result, ConstantPool::cache_offset_in_bytes())); + ldr(cache, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes())); // JNIHandles::resolve(result) ldr(cache, Address(cache, 0)); // Add in the index @@ -308,6 +309,15 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( load_heap_oop(result, Address(cache, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } +void InterpreterMacroAssembler::load_resolved_klass_at_offset( + Register Rcpool, Register Rindex, Register Rklass) { + add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); + ldrh(Rtemp, Address(Rtemp, sizeof(ConstantPool))); // Rtemp = resolved_klass_index + ldr(Rklass, Address(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes())); // Rklass = cpool->_resolved_klasses + add(Rklass, Rklass, AsmOperand(Rtemp, lsl, LogBytesPerWord)); + ldr(Rklass, Address(Rklass, Array::base_offset_in_bytes())); +} + // Generate a subtype check: branch to not_subtype if sub_klass is // not a subtype of super_klass. // Profiling code for the subtype check failure (profile_typecheck_failed) @@ -2016,75 +2026,42 @@ void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, void InterpreterMacroAssembler::get_method_counters(Register method, Register Rcounters, - Label& skip) { + Label& skip, + bool saveRegs, + Register reg1, + Register reg2, + Register reg3) { const Address method_counters(method, Method::method_counters_offset()); Label has_counters; ldr(Rcounters, method_counters); cbnz(Rcounters, has_counters); + if (saveRegs) { + // Save and restore in use caller-saved registers since they will be trashed by call_VM + assert(reg1 != noreg, "must specify reg1"); + assert(reg2 != noreg, "must specify reg2"); #ifdef AARCH64 - const Register tmp = Rcounters; - const int saved_regs_size = 20*wordSize; - - // Note: call_VM will cut SP according to Rstack_top value before call, and restore SP to - // extended_sp value from frame after the call. - // So make sure there is enough stack space to save registers and adjust Rstack_top accordingly. - { - Label enough_stack_space; - check_extended_sp(tmp); - sub(Rstack_top, Rstack_top, saved_regs_size); - cmp(SP, Rstack_top); - b(enough_stack_space, ls); - - align_reg(tmp, Rstack_top, StackAlignmentInBytes); - mov(SP, tmp); - str(tmp, Address(FP, frame::interpreter_frame_extended_sp_offset * wordSize)); - - bind(enough_stack_space); - check_stack_top(); - - int offset = 0; - stp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize; - assert (offset == saved_regs_size, "should be"); - } + assert(reg3 != noreg, "must specify reg3"); + stp(reg1, reg2, Address(Rstack_top, -2*wordSize, pre_indexed)); + stp(reg3, ZR, Address(Rstack_top, -2*wordSize, pre_indexed)); #else - push(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); -#endif // AARCH64 + assert(reg3 == noreg, "must not specify reg3"); + push(RegisterSet(reg1) | RegisterSet(reg2)); +#endif + } mov(R1, method); - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::build_method_counters), R1); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), R1); + if (saveRegs) { #ifdef AARCH64 - { - int offset = 0; - ldp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize; - assert (offset == saved_regs_size, "should be"); - - add(Rstack_top, Rstack_top, saved_regs_size); - } + ldp(reg3, ZR, Address(Rstack_top, 2*wordSize, post_indexed)); + ldp(reg1, reg2, Address(Rstack_top, 2*wordSize, post_indexed)); #else - pop(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); -#endif // AARCH64 + pop(RegisterSet(reg1) | RegisterSet(reg2)); +#endif + } ldr(Rcounters, method_counters); cbz(Rcounters, skip); // No MethodCounters created, OutOfMemory diff --git a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp index 39e60226bf6..434f501bf74 100644 --- a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp +++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp @@ -53,9 +53,6 @@ class InterpreterMacroAssembler: public MacroAssembler { // Template interpreter specific version of call_VM_helper virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(); - virtual void check_and_handle_earlyret(); - // base routine for all dispatches typedef enum { DispatchDefault, DispatchNormal } DispatchTableMode; void dispatch_base(TosState state, DispatchTableMode table_mode, bool verifyoop = true); @@ -63,6 +60,9 @@ class InterpreterMacroAssembler: public MacroAssembler { public: InterpreterMacroAssembler(CodeBuffer* code); + virtual void check_and_handle_popframe(); + virtual void check_and_handle_earlyret(); + // Interpreter-specific registers #if defined(AARCH64) && defined(ASSERT) @@ -141,6 +141,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // Load object from cpool->resolved_references(*bcp+1) void load_resolved_reference_at_index(Register result, Register tmp); + // load cpool->resolved_klass_at(index); Rtemp is corrupted upon return + void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass); + void store_check_part1(Register card_table_base); // Sets card_table_base register. void store_check_part2(Register obj, Register card_table_base, Register tmp); @@ -328,7 +331,13 @@ class InterpreterMacroAssembler: public MacroAssembler { void trace_state(const char* msg) PRODUCT_RETURN; - void get_method_counters(Register method, Register Rcounters, Label& skip); +void get_method_counters(Register method, + Register Rcounters, + Label& skip, + bool saveRegs = false, + Register reg1 = noreg, + Register reg2 = noreg, + Register reg3 = noreg); }; #endif // CPU_ARM_VM_INTERP_MASM_ARM_HPP diff --git a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp index e6f73353cb9..b0710a1518a 100644 --- a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp +++ b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp @@ -206,6 +206,9 @@ protected: // may customize this version by overriding it for its purposes (e.g., to save/restore // additional registers when doing a VM call). virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); +public: + + MacroAssembler(CodeBuffer* code) : Assembler(code) {} // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. // The implementation is only non-empty for the InterpreterMacroAssembler, @@ -213,10 +216,6 @@ protected: virtual void check_and_handle_popframe() {} virtual void check_and_handle_earlyret() {} -public: - - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - // By default, we do not need relocation information for non // patchable absolute addresses. However, when needed by some // extensions, ignore_non_patchable_relocations can be modified, diff --git a/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp b/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp deleted file mode 100644 index 1cda4dff24e..00000000000 --- a/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "assembler_arm.inline.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - for (int i = 0; i < vtbl_list_size; ++i) { - Label common_code; - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*) __ pc(); - __ mov(Rtemp, j); // Rtemp contains an index of a virtual method in the table - __ b(common_code); - } - - InlinedAddress vtable_address((address)&vtbl_list[i]); - __ bind(common_code); - const Register tmp2 = AARCH64_ONLY(Rtemp2) NOT_AARCH64(R4); - assert_different_registers(Rtemp, tmp2); -#ifndef AARCH64 - __ push(tmp2); -#endif // !AARCH64 - // Do not use ldr_global since the code must be portable across all ARM architectures - __ ldr_literal(tmp2, vtable_address); - __ ldr(tmp2, Address(tmp2)); // get correct vtable address - __ ldr(Rtemp, Address::indexed_ptr(tmp2, Rtemp)); // get real method pointer - __ str(tmp2, Address(R0)); // update vtable. R0 = "this" -#ifndef AARCH64 - __ pop(tmp2); -#endif // !AARCH64 - __ jump(Rtemp); - __ bind_literal(vtable_address); - } - - __ flush(); - *mc_top = (char*) __ pc(); -} diff --git a/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp b/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp index 15317969319..d0794e4c525 100644 --- a/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp +++ b/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -67,7 +67,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, Register temp1, Register temp2, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Label L_ok, L_bad; BLOCK_COMMENT("verify_klass {"); __ verify_oop(obj); @@ -157,8 +157,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ load_heap_oop(tmp, Address(tmp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(tmp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ ldr(Rmethod, Address(tmp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + __ load_heap_oop(Rmethod, Address(tmp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(Rmethod); + __ ldr(Rmethod, Address(Rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -320,7 +321,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method(Rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -375,14 +377,17 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ ldr(Rmethod, member_vmtarget); + __ load_heap_oop(Rmethod, member_vmtarget); + __ ldr(Rmethod, vmtarget_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ ldr(Rmethod, member_vmtarget); + __ load_heap_oop(Rmethod, member_vmtarget); + __ ldr(Rmethod, vmtarget_method); + break; break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp index 7fda747ad48..94a2bd7e8e7 100644 --- a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp @@ -270,12 +270,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - // Not used. - STOP("generate_continuation_for"); - return NULL; -} - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -310,6 +304,9 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ convert_retval_to_tos(state); #endif // !AARCH64 + __ check_and_handle_popframe(); + __ check_and_handle_earlyret(); + __ dispatch_next(state, step); return entry; @@ -1401,7 +1398,13 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef AARCH64 // setup RmaxStack __ ldrh(RmaxStack, Address(RconstMethod, ConstMethod::max_stack_offset())); - __ add(RmaxStack, RmaxStack, MAX2(1, Method::extra_stack_entries())); // reserve slots for exception handler and JSR292 appendix argument + // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots, + // none of which are at the same time, so we just need to make sure there is enough room + // for the biggest user: + // -reserved slot for exception handler + // -reserved slots for JSR292. Method::extra_stack_entries() is the size. + // -3 reserved slots so get_method_counters() can save some registers before call_VM(). + __ add(RmaxStack, RmaxStack, MAX2(3, Method::extra_stack_entries())); #endif // AARCH64 // see if we've got enough room on the stack for locals plus overhead. diff --git a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp index c8711b830eb..7fd60ce8d2d 100644 --- a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -2286,13 +2286,18 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { } __ bind(no_mdo); // Increment backedge counter in MethodCounters* - __ get_method_counters(Rmethod, Rcounters, dispatch); + // Note Rbumped_taken_count is a callee saved registers for ARM32, but caller saved for ARM64 + __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/, + Rdisp, R3_bytecode, + AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg)); const Address mask(Rcounters, in_bytes(MethodCounters::backedge_mask_offset())); __ increment_mask_and_jump(Address(Rcounters, be_offset), increment, mask, Rcnt, R4_tmp, eq, &backedge_counter_overflow); } else { - // increment counter - __ get_method_counters(Rmethod, Rcounters, dispatch); + // Increment backedge counter in MethodCounters* + __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/, + Rdisp, R3_bytecode, + AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg)); __ ldr_u32(Rtemp, Address(Rcounters, be_offset)); // load backedge counter __ add(Rtemp, Rtemp, InvocationCounter::count_increment); // increment counter __ str_32(Rtemp, Address(Rcounters, be_offset)); // store counter @@ -4367,10 +4372,9 @@ void TemplateTable::_new() { #endif // AARCH64 // get InstanceKlass - __ add(Rklass, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Rklass, Address(Rklass, sizeof(ConstantPool))); __ cmp(Rtemp, JVM_CONSTANT_Class); __ b(slow_case, ne); + __ load_resolved_klass_at_offset(Rcpool, Rindex, Rklass); // make sure klass is initialized & doesn't have finalizer // make sure klass is fully initialized @@ -4642,8 +4646,7 @@ void TemplateTable::checkcast() { // Get superklass in Rsuper and subklass in Rsub __ bind(quicked); - __ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper); __ bind(resolved); __ load_klass(Rsub, Robj); @@ -4716,8 +4719,7 @@ void TemplateTable::instanceof() { // Get superklass in Rsuper and subklass in Rsub __ bind(quicked); - __ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper); __ bind(resolved); __ load_klass(Rsub, Robj); diff --git a/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp b/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp index 10a2408772d..b59c2d3864d 100644 --- a/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp +++ b/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp @@ -256,7 +256,9 @@ void VM_Version::initialize() { } } - AllocatePrefetchDistance = 128; + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 128); + } #ifdef COMPILER2 FLAG_SET_DEFAULT(UseFPUForSpilling, true); diff --git a/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp b/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp index 7f25255d72f..981ec128ab5 100644 --- a/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp +++ b/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp @@ -201,7 +201,9 @@ void VM_Version::initialize() { } } - AllocatePrefetchDistance = 128; + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 128); + } #ifdef COMPILER2 FLAG_SET_DEFAULT(UseFPUForSpilling, true); diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp index 09217a42bb5..a64e2ed2b44 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp @@ -376,10 +376,12 @@ class Assembler : public AbstractAssembler { STWX_OPCODE = (31u << OPCODE_SHIFT | 151u << 1), STWU_OPCODE = (37u << OPCODE_SHIFT), STWUX_OPCODE = (31u << OPCODE_SHIFT | 183u << 1), + STWBRX_OPCODE = (31u << OPCODE_SHIFT | 662u << 1), STH_OPCODE = (44u << OPCODE_SHIFT), STHX_OPCODE = (31u << OPCODE_SHIFT | 407u << 1), STHU_OPCODE = (45u << OPCODE_SHIFT), + STHBRX_OPCODE = (31u << OPCODE_SHIFT | 918u << 1), STB_OPCODE = (38u << OPCODE_SHIFT), STBX_OPCODE = (31u << OPCODE_SHIFT | 215u << 1), @@ -401,11 +403,13 @@ class Assembler : public AbstractAssembler { LD_OPCODE = (58u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM LDU_OPCODE = (58u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM LDX_OPCODE = (31u << OPCODE_SHIFT | 21u << XO_21_30_SHIFT), // X-FORM + LDBRX_OPCODE = (31u << OPCODE_SHIFT | 532u << 1), // X-FORM STD_OPCODE = (62u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM STDU_OPCODE = (62u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM - STDUX_OPCODE = (31u << OPCODE_SHIFT | 181u << 1), // X-FORM + STDUX_OPCODE = (31u << OPCODE_SHIFT | 181u << 1), // X-FORM STDX_OPCODE = (31u << OPCODE_SHIFT | 149u << XO_21_30_SHIFT), // X-FORM + STDBRX_OPCODE = (31u << OPCODE_SHIFT | 660u << 1), // X-FORM RLDICR_OPCODE = (30u << OPCODE_SHIFT | 1u << XO_27_29_SHIFT), // MD-FORM RLDICL_OPCODE = (30u << OPCODE_SHIFT | 0u << XO_27_29_SHIFT), // MD-FORM @@ -1552,6 +1556,9 @@ class Assembler : public AbstractAssembler { inline void ld( Register d, int si16, Register s1); inline void ldu( Register d, int si16, Register s1); + // 8 bytes reversed + inline void ldbrx( Register d, Register s1, Register s2); + // For convenience. Load pointer into d from b+s1. inline void ld_ptr(Register d, int b, Register s1); DEBUG_ONLY(inline void ld_ptr(Register d, ByteSize b, Register s1);) @@ -1560,10 +1567,12 @@ class Assembler : public AbstractAssembler { inline void stwx( Register d, Register s1, Register s2); inline void stw( Register d, int si16, Register s1); inline void stwu( Register d, int si16, Register s1); + inline void stwbrx( Register d, Register s1, Register s2); inline void sthx( Register d, Register s1, Register s2); inline void sth( Register d, int si16, Register s1); inline void sthu( Register d, int si16, Register s1); + inline void sthbrx( Register d, Register s1, Register s2); inline void stbx( Register d, Register s1, Register s2); inline void stb( Register d, int si16, Register s1); @@ -1573,6 +1582,7 @@ class Assembler : public AbstractAssembler { inline void std( Register d, int si16, Register s1); inline void stdu( Register d, int si16, Register s1); inline void stdux(Register s, Register a, Register b); + inline void stdbrx( Register d, Register s1, Register s2); inline void st_ptr(Register d, int si16, Register s1); DEBUG_ONLY(inline void st_ptr(Register d, ByteSize b, Register s1);) @@ -2182,14 +2192,18 @@ class Assembler : public AbstractAssembler { inline void lbz( Register d, int si16); inline void ldx( Register d, Register s2); inline void ld( Register d, int si16); + inline void ldbrx(Register d, Register s2); inline void stwx( Register d, Register s2); inline void stw( Register d, int si16); + inline void stwbrx( Register d, Register s2); inline void sthx( Register d, Register s2); inline void sth( Register d, int si16); + inline void sthbrx( Register d, Register s2); inline void stbx( Register d, Register s2); inline void stb( Register d, int si16); inline void stdx( Register d, Register s2); inline void std( Register d, int si16); + inline void stdbrx( Register d, Register s2); // PPC 2, section 3.2.1 Instruction Cache Instructions inline void icbi( Register s2); diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp index 7f42d6b6050..602ae02179c 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp @@ -327,6 +327,7 @@ inline void Assembler::lbzu( Register d, int si16, Register s1) { assert(d != inline void Assembler::ld( Register d, int si16, Register s1) { emit_int32(LD_OPCODE | rt(d) | ds(si16) | ra0mem(s1));} inline void Assembler::ldx( Register d, Register s1, Register s2) { emit_int32(LDX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::ldu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LDU_OPCODE | rt(d) | ds(si16) | rta0mem(s1));} +inline void Assembler::ldbrx( Register d, Register s1, Register s2) { emit_int32(LDBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::ld_ptr(Register d, int b, Register s1) { ld(d, b, s1); } DEBUG_ONLY(inline void Assembler::ld_ptr(Register d, ByteSize b, Register s1) { ld(d, in_bytes(b), s1); }) @@ -335,10 +336,12 @@ DEBUG_ONLY(inline void Assembler::ld_ptr(Register d, ByteSize b, Register s1) { inline void Assembler::stwx( Register d, Register s1, Register s2) { emit_int32(STWX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stw( Register d, int si16, Register s1) { emit_int32(STW_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} inline void Assembler::stwu( Register d, int si16, Register s1) { emit_int32(STWU_OPCODE | rs(d) | d1(si16) | rta0mem(s1));} +inline void Assembler::stwbrx( Register d, Register s1, Register s2) { emit_int32(STWBRX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::sthx( Register d, Register s1, Register s2) { emit_int32(STHX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::sth( Register d, int si16, Register s1) { emit_int32(STH_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} inline void Assembler::sthu( Register d, int si16, Register s1) { emit_int32(STHU_OPCODE | rs(d) | d1(si16) | rta0mem(s1));} +inline void Assembler::sthbrx( Register d, Register s1, Register s2) { emit_int32(STHBRX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stbx( Register d, Register s1, Register s2) { emit_int32(STBX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stb( Register d, int si16, Register s1) { emit_int32(STB_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} @@ -348,6 +351,7 @@ inline void Assembler::std( Register d, int si16, Register s1) { emit_int32( inline void Assembler::stdx( Register d, Register s1, Register s2) { emit_int32(STDX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stdu( Register d, int si16, Register s1) { emit_int32(STDU_OPCODE | rs(d) | ds(si16) | rta0mem(s1));} inline void Assembler::stdux(Register s, Register a, Register b) { emit_int32(STDUX_OPCODE| rs(s) | rta0mem(a) | rb(b));} +inline void Assembler::stdbrx( Register d, Register s1, Register s2) { emit_int32(STDBRX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::st_ptr(Register d, int b, Register s1) { std(d, b, s1); } DEBUG_ONLY(inline void Assembler::st_ptr(Register d, ByteSize b, Register s1) { std(d, in_bytes(b), s1); }) @@ -944,14 +948,18 @@ inline void Assembler::lbzx( Register d, Register s2) { emit_int32( LBZX_OPCODE inline void Assembler::lbz( Register d, int si16 ) { emit_int32( LBZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::ld( Register d, int si16 ) { emit_int32( LD_OPCODE | rt(d) | ds(si16));} inline void Assembler::ldx( Register d, Register s2) { emit_int32( LDX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::ldbrx(Register d, Register s2) { emit_int32( LDBRX_OPCODE| rt(d) | rb(s2));} inline void Assembler::stwx( Register d, Register s2) { emit_int32( STWX_OPCODE | rs(d) | rb(s2));} inline void Assembler::stw( Register d, int si16 ) { emit_int32( STW_OPCODE | rs(d) | d1(si16));} +inline void Assembler::stwbrx(Register d, Register s2){ emit_int32(STWBRX_OPCODE| rs(d) | rb(s2));} inline void Assembler::sthx( Register d, Register s2) { emit_int32( STHX_OPCODE | rs(d) | rb(s2));} inline void Assembler::sth( Register d, int si16 ) { emit_int32( STH_OPCODE | rs(d) | d1(si16));} +inline void Assembler::sthbrx(Register d, Register s2){ emit_int32(STHBRX_OPCODE| rs(d) | rb(s2));} inline void Assembler::stbx( Register d, Register s2) { emit_int32( STBX_OPCODE | rs(d) | rb(s2));} inline void Assembler::stb( Register d, int si16 ) { emit_int32( STB_OPCODE | rs(d) | d1(si16));} inline void Assembler::std( Register d, int si16 ) { emit_int32( STD_OPCODE | rs(d) | ds(si16));} inline void Assembler::stdx( Register d, Register s2) { emit_int32( STDX_OPCODE | rs(d) | rb(s2));} +inline void Assembler::stdbrx(Register d, Register s2){ emit_int32(STDBRX_OPCODE| rs(d) | rb(s2));} // ra0 version inline void Assembler::icbi( Register s2) { emit_int32( ICBI_OPCODE | rb(s2) ); } diff --git a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp index b75b0f0fa5d..ac16dcb872d 100644 --- a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp @@ -37,10 +37,6 @@ class Bytes: AllStatic { #if defined(VM_LITTLE_ENDIAN) - // Returns true, if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. - static inline bool is_Java_byte_ordering_different() { return true; } - // Forward declarations of the compiler-dependent implementation static inline u2 swap_u2(u2 x); static inline u4 swap_u4(u4 x); @@ -155,10 +151,6 @@ class Bytes: AllStatic { #else // !defined(VM_LITTLE_ENDIAN) - // Returns true, if the byte ordering used by Java is different from the nativ byte ordering - // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. - static inline bool is_Java_byte_ordering_different() { return false; } - // Thus, a swap between native and Java ordering is always a no-op: static inline u2 swap_u2(u2 x) { return x; } static inline u4 swap_u4(u4 x) { return x; } diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp index 127403fde2f..b64e3cd8a4a 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3177,9 +3177,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { assert_different_registers(val, crc, res); __ load_const_optimized(res, StubRoutines::crc_table_addr(), R0); - __ nand(crc, crc, crc); // ~crc - __ update_byte_crc32(crc, val, res); - __ nand(res, crc, crc); // ~crc + __ kernel_crc32_singleByteReg(crc, val, res, true); + __ mr(res, crc); } #undef __ diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp index 5bcd457e7e0..e5b54680132 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,18 +63,6 @@ void LIRItem::load_nonconstant() { } -inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) { - LIR_Opr r = li.value()->operand(); - if (r->is_register()) { - LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register()); - ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert. - } else { - // Constants or memory get loaded with sign extend on this platform. - ll->move(li.result(), dst); - } -} - - //-------------------------------------------------------------- // LIRGenerator //-------------------------------------------------------------- @@ -1426,10 +1414,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { arg2 = cc->at(1), arg3 = cc->at(2); - // CCallingConventionRequiresIntsAsLongs crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. __ leal(LIR_OprFact::address(a), arg2); - load_int_as_long(gen()->lir(), len, arg3); + len.load_item_force(arg3); // We skip int->long conversion here, , because CRC32 stub expects int. __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ move(result_reg, result); @@ -1441,6 +1428,76 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } } +void LIRGenerator::do_update_CRC32C(Intrinsic* x) { + assert(UseCRC32CIntrinsics, "or should not be here"); + LIR_Opr result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: { + bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C); + + LIRItem crc(x->argument_at(0), this); + LIRItem buf(x->argument_at(1), this); + LIRItem off(x->argument_at(2), this); + LIRItem end(x->argument_at(3), this); + buf.load_item(); + off.load_nonconstant(); + end.load_nonconstant(); + + // len = end - off + LIR_Opr len = end.result(); + LIR_Opr tmpA = new_register(T_INT); + LIR_Opr tmpB = new_register(T_INT); + __ move(end.result(), tmpA); + __ move(off.result(), tmpB); + __ sub(tmpA, tmpB, tmpA); + len = tmpA; + + LIR_Opr index = off.result(); + int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0; + if (off.result()->is_constant()) { + index = LIR_OprFact::illegalOpr; + offset += off.result()->as_jint(); + } + LIR_Opr base_op = buf.result(); + LIR_Address* a = NULL; + + if (index->is_valid()) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index, tmp); + index = tmp; + __ add(index, LIR_OprFact::intptrConst(offset), index); + a = new LIR_Address(base_op, index, T_BYTE); + } else { + a = new LIR_Address(base_op, offset, T_BYTE); + } + + BasicTypeList signature(3); + signature.append(T_INT); + signature.append(T_ADDRESS); + signature.append(T_INT); + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + const LIR_Opr result_reg = result_register_for(x->type()); + + LIR_Opr arg1 = cc->at(0), + arg2 = cc->at(1), + arg3 = cc->at(2); + + crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32C stub doesn't care about high bits. + __ leal(LIR_OprFact::address(a), arg2); + __ move(len, cc->at(2)); // We skip int->long conversion here, because CRC32C stub expects int. + + __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args()); + __ move(result_reg, result); + break; + } + default: { + ShouldNotReachHere(); + } + } +} + void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { assert(x->number_of_arguments() == 3, "wrong type"); assert(UseFMA, "Needs FMA instructions support."); @@ -1467,7 +1524,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } - -void LIRGenerator::do_update_CRC32C(Intrinsic* x) { - Unimplemented(); -} diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index bf4ca17df09..8e0656ba215 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -164,7 +164,7 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); product(bool, ZapMemory, false, "Write 0x0101... to empty memory." \ " Use this to ease debugging.") \ \ - /* Use Restricted Transactional Memory for lock eliding */ \ + /* Use Restricted Transactional Memory for lock elision */ \ product(bool, UseRTMLocking, false, \ "Enable RTM lock eliding for inflated locks in compiled code") \ \ @@ -174,24 +174,30 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); product(bool, UseRTMDeopt, false, \ "Perform deopt and recompilation based on RTM abort ratio") \ \ - product(uintx, RTMRetryCount, 5, \ + product(int, RTMRetryCount, 5, \ "Number of RTM retries on lock abort or busy") \ + range(0, max_jint) \ \ - experimental(intx, RTMSpinLoopCount, 100, \ + experimental(int, RTMSpinLoopCount, 100, \ "Spin count for lock to become free before RTM retry") \ + range(0, 32767) /* immediate operand limit on ppc */ \ \ - experimental(intx, RTMAbortThreshold, 1000, \ + experimental(int, RTMAbortThreshold, 1000, \ "Calculate abort ratio after this number of aborts") \ + range(0, max_jint) \ \ - experimental(intx, RTMLockingThreshold, 10000, \ + experimental(int, RTMLockingThreshold, 10000, \ "Lock count at which to do RTM lock eliding without " \ "abort ratio calculation") \ + range(0, max_jint) \ \ - experimental(intx, RTMAbortRatio, 50, \ + experimental(int, RTMAbortRatio, 50, \ "Lock abort ratio at which to stop use RTM lock eliding") \ + range(0, 100) /* natural range, checked in vm_version_ppc.cpp */ \ \ - experimental(intx, RTMTotalCountIncrRate, 64, \ + experimental(int, RTMTotalCountIncrRate, 64, \ "Increment total RTM attempted lock count once every n times") \ + range(1, 32767) /* immediate operand limit on ppc */ \ \ experimental(intx, RTMLockingCalculationDelay, 0, \ "Number of milliseconds to wait before start calculating aborts " \ diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp index d2085ea4e78..19f91e98633 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,8 +45,8 @@ class InterpreterMacroAssembler: public MacroAssembler { #define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread #define method_(field_name) in_bytes(Method::field_name ## _offset()), R19_method - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); + virtual void check_and_handle_popframe(Register scratch_reg); + virtual void check_and_handle_earlyret(Register scratch_reg); // Base routine for all dispatches. void dispatch_base(TosState state, address* table); @@ -79,6 +79,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // Load object from cpool->resolved_references(index). void load_resolved_reference_at_index(Register result, Register index, Label *is_null = NULL); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass); + void load_receiver(Register Rparam_count, Register Rrecv_dst); // helpers for expression stack diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 95234115319..a477079fc59 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -454,7 +454,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result Register tmp = index; // reuse sldi(tmp, index, LogBytesPerHeapOop); // Load pointer for resolved_references[] objArray. - ld(result, ConstantPool::resolved_references_offset_in_bytes(), result); + ld(result, ConstantPool::cache_offset_in_bytes(), result); + ld(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result); // JNIHandles::resolve(result) ld(result, 0, result); #ifdef ASSERT @@ -471,6 +472,25 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null); } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass) { + // int value = *(Rcpool->int_at_addr(which)); + // int resolved_klass_index = extract_low_short_from_int(value); + add(Roffset, Rcpool, Roffset); +#if defined(VM_LITTLE_ENDIAN) + lhz(Roffset, sizeof(ConstantPool), Roffset); // Roffset = resolved_klass_index +#else + lhz(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index +#endif + + ld(Rklass, ConstantPool::resolved_klasses_offset_in_bytes(), Rcpool); // Rklass = Rcpool->_resolved_klasses + + sldi(Roffset, Roffset, LogBytesPerWord); + addi(Roffset, Roffset, Array::base_offset_in_bytes()); + isync(); // Order load of instance Klass wrt. tags. + ldx(Rklass, Rklass, Roffset); +} + // Generate a subtype check: branch to ok_is_subtype if sub_klass is // a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2. void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1, diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index 6eb27c78f17..f8dd94c23df 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2498,14 +2498,20 @@ void MacroAssembler::rtm_abort_ratio_calculation(Register rtm_counters_Reg, // All transactions = total_count * RTMTotalCountIncrRate // Set no_rtm bit if (Aborted transactions >= All transactions * RTMAbortRatio) ld(R0, RTMLockingCounters::abort_count_offset(), rtm_counters_Reg); - cmpdi(CCR0, R0, RTMAbortThreshold); - blt(CCR0, L_check_always_rtm2); + if (is_simm(RTMAbortThreshold, 16)) { // cmpdi can handle 16bit immediate only. + cmpdi(CCR0, R0, RTMAbortThreshold); + blt(CCR0, L_check_always_rtm2); // reload of rtm_counters_Reg not necessary + } else { + load_const_optimized(rtm_counters_Reg, RTMAbortThreshold); + cmpd(CCR0, R0, rtm_counters_Reg); + blt(CCR0, L_check_always_rtm1); // reload of rtm_counters_Reg required + } mulli(R0, R0, 100); const Register tmpReg = rtm_counters_Reg; ld(tmpReg, RTMLockingCounters::total_count_offset(), rtm_counters_Reg); - mulli(tmpReg, tmpReg, RTMTotalCountIncrRate); - mulli(tmpReg, tmpReg, RTMAbortRatio); + mulli(tmpReg, tmpReg, RTMTotalCountIncrRate); // allowable range: int16 + mulli(tmpReg, tmpReg, RTMAbortRatio); // allowable range: int16 cmpd(CCR0, R0, tmpReg); blt(CCR0, L_check_always_rtm1); // jump to reload if (method_data != NULL) { @@ -2521,7 +2527,13 @@ void MacroAssembler::rtm_abort_ratio_calculation(Register rtm_counters_Reg, load_const_optimized(rtm_counters_Reg, (address)rtm_counters, R0); // reload bind(L_check_always_rtm2); ld(tmpReg, RTMLockingCounters::total_count_offset(), rtm_counters_Reg); - cmpdi(CCR0, tmpReg, RTMLockingThreshold / RTMTotalCountIncrRate); + int64_t thresholdValue = RTMLockingThreshold / RTMTotalCountIncrRate; + if (is_simm(thresholdValue, 16)) { // cmpdi can handle 16bit immediate only. + cmpdi(CCR0, tmpReg, thresholdValue); + } else { + load_const_optimized(R0, thresholdValue); + cmpd(CCR0, tmpReg, R0); + } blt(CCR0, L_done); if (method_data != NULL) { // Set rtm_state to "always rtm" in MDO. @@ -2620,7 +2632,7 @@ void MacroAssembler::rtm_stack_locking(ConditionRegister flag, if (PrintPreciseRTMLockingStatistics || profile_rtm) { Label L_noincrement; if (RTMTotalCountIncrRate > 1) { - branch_on_random_using_tb(tmp, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_tb(tmp, RTMTotalCountIncrRate, L_noincrement); } assert(stack_rtm_counters != NULL, "should not be NULL when profiling RTM"); load_const_optimized(tmp, (address)stack_rtm_counters->total_count_addr(), R0); @@ -2687,7 +2699,7 @@ void MacroAssembler::rtm_inflated_locking(ConditionRegister flag, if (PrintPreciseRTMLockingStatistics || profile_rtm) { Label L_noincrement; if (RTMTotalCountIncrRate > 1) { - branch_on_random_using_tb(R0, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_tb(R0, RTMTotalCountIncrRate, L_noincrement); } assert(rtm_counters != NULL, "should not be NULL when profiling RTM"); load_const(R0, (address)rtm_counters->total_count_addr(), tmpReg); @@ -4120,7 +4132,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl * @param table register pointing to CRC table */ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool loopAlignment, bool invertCRC) { + Register data, bool loopAlignment) { assert_different_registers(crc, buf, len, table, data); Label L_mainLoop, L_done; @@ -4131,10 +4143,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register clrldi_(len, len, 32); // Enforce 32 bit. Anything to do? beq(CCR0, L_done); - if (invertCRC) { - nand(crc, crc, crc); // ~c - } - mtctr(len); align(mainLoop_alignment); BIND(L_mainLoop); @@ -4143,10 +4151,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register update_byte_crc32(crc, data, table); bdnz(L_mainLoop); // Iterate. - if (invertCRC) { - nand(crc, crc, crc); // ~c - } - bind(L_done); } @@ -4203,7 +4207,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab */ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, Register t0, Register t1, Register t2, Register t3, - Register tc0, Register tc1, Register tc2, Register tc3) { + Register tc0, Register tc1, Register tc2, Register tc3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -4217,14 +4222,16 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len const int complexThreshold = 2*mainLoop_stepping; // Don't test for len <= 0 here. This pathological case should not occur anyway. - // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles. - // The situation itself is detected and handled correctly by the conditional branches - // following aghi(len, -stepping) and aghi(len, +stepping). + // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles + // for all well-behaved cases. The situation itself is detected and handled correctly + // within update_byteLoop_crc32. assert(tailLoop_stepping == 1, "check tailLoop_stepping!"); BLOCK_COMMENT("kernel_crc32_2word {"); - nand(crc, crc, crc); // ~c + if (invertCRC) { + nand(crc, crc, crc); // 1s complement of crc + } // Check for short (=mainLoop_stepping is guaranteed). } - update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); + update_byteLoop_crc32(crc, buf, tmp2, table, data, false); } srdi(tmp2, len, log_stepping); // #iterations for mainLoop @@ -4281,9 +4288,11 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len // Process last few (=mainLoop_stepping is guaranteed). } - update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); + update_byteLoop_crc32(crc, buf, tmp2, table, data, false); } srdi(tmp2, len, log_stepping); // #iterations for mainLoop @@ -4374,9 +4386,11 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len // Process last few (klass()->klass_part()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no releationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - // There are more general problems with CDS on ppc, so I can not - // really test this. But having this instead of Unimplementd() allows - // us to pass TestOptionsWithRanges.java. - __ unimplemented(); -} - diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp index a4bb111d9e0..acc8dcc09bc 100644 --- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -71,7 +71,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register temp_reg, Register temp2_reg, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Label L_ok, L_bad; BLOCK_COMMENT("verify_klass {"); __ verify_oop(obj_reg); @@ -174,8 +174,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2); __ verify_oop(method_temp); - // The following assumes that a Method* is normally compressed in the vmtarget field: - __ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp); + __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), method_temp); + __ verify_oop(method_temp); + __ ld(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), method_temp); if (VerifyMethodHandles && !for_compiler_entry) { // Make sure recv is already on stack. @@ -361,14 +362,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2); } - __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); + __ load_heap_oop(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg); + __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), member_reg); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2); } - __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); + __ load_heap_oop(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg); + __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), member_reg); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index 6c3d9cf1fda..a5ad8efab2f 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2012, 2016 SAP SE. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -2053,12 +2053,12 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg. -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize == 8 && size == 8, ""); return Op_RegL; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { fatal("vector shift is not supported"); return Node::NotAMachineReg; } @@ -5842,6 +5842,16 @@ instruct loadConN_lo(iRegNdst dst, iRegNsrc src1, immN src2) %{ ins_pipe(pipe_class_default); %} +instruct rldicl(iRegLdst dst, iRegLsrc src, immI16 shift, immI16 mask_begin) %{ + effect(DEF dst, USE src, USE shift, USE mask_begin); + + size(4); + ins_encode %{ + __ rldicl($dst$$Register, $src$$Register, $shift$$constant, $mask_begin$$constant); + %} + ins_pipe(pipe_class_default); +%} + // Needed to postalloc expand loadConN: ConN is loaded as ConI // leaving the upper 32 bits with sign-extension bits. // This clears these bits: dst = src & 0xFFFFFFFF. @@ -10519,6 +10529,16 @@ instruct convB2I_reg(iRegIdst dst, iRegIsrc src, immI_24 amount) %{ ins_pipe(pipe_class_default); %} +instruct extsh(iRegIdst dst, iRegIsrc src) %{ + effect(DEF dst, USE src); + + size(4); + ins_encode %{ + __ extsh($dst$$Register, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + // LShiftI 16 + RShiftI 16 converts short to int. instruct convS2I_reg(iRegIdst dst, iRegIsrc src, immI_16 amount) %{ match(Set dst (RShiftI (LShiftI src amount) amount)); @@ -12682,8 +12702,7 @@ instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ // Just slightly faster than java implementation. instruct bytes_reverse_int_Ex(iRegIdst dst, iRegIsrc src) %{ match(Set dst (ReverseBytesI src)); - predicate(UseCountLeadingZerosInstructionsPPC64); - ins_cost(DEFAULT_COST); + ins_cost(7*DEFAULT_COST); expand %{ immI16 imm24 %{ (int) 24 %} @@ -12705,6 +12724,172 @@ instruct bytes_reverse_int_Ex(iRegIdst dst, iRegIsrc src) %{ %} %} +instruct bytes_reverse_long_Ex(iRegLdst dst, iRegLsrc src) %{ + match(Set dst (ReverseBytesL src)); + ins_cost(15*DEFAULT_COST); + + expand %{ + immI16 imm56 %{ (int) 56 %} + immI16 imm48 %{ (int) 48 %} + immI16 imm40 %{ (int) 40 %} + immI16 imm32 %{ (int) 32 %} + immI16 imm24 %{ (int) 24 %} + immI16 imm16 %{ (int) 16 %} + immI16 imm8 %{ (int) 8 %} + immI16 imm0 %{ (int) 0 %} + iRegLdst tmpL1; + iRegLdst tmpL2; + iRegLdst tmpL3; + iRegLdst tmpL4; + iRegLdst tmpL5; + iRegLdst tmpL6; + + // src : |a|b|c|d|e|f|g|h| + rldicl(tmpL1, src, imm8, imm24); // tmpL1 : | | | |e|f|g|h|a| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |a| | | |e| + rldicl(tmpL3, tmpL2, imm32, imm0); // tmpL3 : | | | |e| | | |a| + rldicl(tmpL1, src, imm16, imm24); // tmpL1 : | | | |f|g|h|a|b| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |b| | | |f| + rldicl(tmpL4, tmpL2, imm40, imm0); // tmpL4 : | | |f| | | |b| | + orL_reg_reg(tmpL5, tmpL3, tmpL4); // tmpL5 : | | |f|e| | |b|a| + rldicl(tmpL1, src, imm24, imm24); // tmpL1 : | | | |g|h|a|b|c| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |c| | | |g| + rldicl(tmpL3, tmpL2, imm48, imm0); // tmpL3 : | |g| | | |c| | | + rldicl(tmpL1, src, imm32, imm24); // tmpL1 : | | | |h|a|b|c|d| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |d| | | |h| + rldicl(tmpL4, tmpL2, imm56, imm0); // tmpL4 : |h| | | |d| | | | + orL_reg_reg(tmpL6, tmpL3, tmpL4); // tmpL6 : |h|g| | |d|c| | | + orL_reg_reg(dst, tmpL5, tmpL6); // dst : |h|g|f|e|d|c|b|a| + %} +%} + +instruct bytes_reverse_ushort_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (ReverseBytesUS src)); + ins_cost(2*DEFAULT_COST); + + expand %{ + immI16 imm16 %{ (int) 16 %} + immI16 imm8 %{ (int) 8 %} + + urShiftI_reg_imm(dst, src, imm8); + insrwi(dst, src, imm16, imm8); + %} +%} + +instruct bytes_reverse_short_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (ReverseBytesS src)); + ins_cost(3*DEFAULT_COST); + + expand %{ + immI16 imm16 %{ (int) 16 %} + immI16 imm8 %{ (int) 8 %} + iRegLdst tmpI1; + + urShiftI_reg_imm(tmpI1, src, imm8); + insrwi(tmpI1, src, imm16, imm8); + extsh(dst, tmpI1); + %} +%} + +// Load Integer reversed byte order +instruct loadI_reversed(iRegIdst dst, indirect mem) %{ + match(Set dst (ReverseBytesI (LoadI mem))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ lwbrx($dst$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Load Long - aligned and reversed +instruct loadL_reversed(iRegLdst dst, indirect mem) %{ + match(Set dst (ReverseBytesL (LoadL mem))); + predicate(VM_Version::has_ldbrx()); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ ldbrx($dst$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Load unsigned short / char reversed byte order +instruct loadUS_reversed(iRegIdst dst, indirect mem) %{ + match(Set dst (ReverseBytesUS (LoadUS mem))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ lhbrx($dst$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Load short reversed byte order +instruct loadS_reversed(iRegIdst dst, indirect mem) %{ + match(Set dst (ReverseBytesS (LoadS mem))); + ins_cost(MEMORY_REF_COST + DEFAULT_COST); + + size(8); + ins_encode %{ + __ lhbrx($dst$$Register, $mem$$Register); + __ extsh($dst$$Register, $dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store Integer reversed byte order +instruct storeI_reversed(iRegIsrc src, indirect mem) %{ + match(Set mem (StoreI mem (ReverseBytesI src))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ stwbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store Long reversed byte order +instruct storeL_reversed(iRegLsrc src, indirect mem) %{ + match(Set mem (StoreL mem (ReverseBytesL src))); + predicate(VM_Version::has_stdbrx()); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ stdbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store unsigned short / char reversed byte order +instruct storeUS_reversed(iRegIsrc src, indirect mem) %{ + match(Set mem (StoreC mem (ReverseBytesUS src))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ sthbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store short reversed byte order +instruct storeS_reversed(iRegIsrc src, indirect mem) %{ + match(Set mem (StoreC mem (ReverseBytesS src))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ sthbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + //---------- Replicate Vector Instructions ------------------------------------ // Insrdi does replicate if src == dst. diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 4bd0c833ab8..90cd5ccf718 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3276,6 +3276,36 @@ class StubGenerator: public StubCodeGenerator { return start; } + + // Compute CRC32/CRC32C function. + void generate_CRC_updateBytes(const char* name, Register table, bool invertCRC) { + + // arguments to kernel_crc32: + const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. + const Register data = R4_ARG2; // source byte array + const Register dataLen = R5_ARG3; // #bytes to process + + const Register t0 = R2; + const Register t1 = R7; + const Register t2 = R8; + const Register t3 = R9; + const Register tc0 = R10; + const Register tc1 = R11; + const Register tc2 = R12; + + BLOCK_COMMENT("Stub body {"); + assert_different_registers(crc, data, dataLen, table); + + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table, invertCRC); + + BLOCK_COMMENT("return"); + __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). + __ blr(); + + BLOCK_COMMENT("} Stub body"); + } + + /** * Arguments: * @@ -3296,14 +3326,14 @@ class StubGenerator: public StubCodeGenerator { StubCodeMark mark(this, "StubRoutines", name); address start = __ function_entry(); // Remember stub start address (is rtn value). + const Register table = R6; // crc table address + +#ifdef VM_LITTLE_ENDIAN // arguments to kernel_crc32: const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. const Register data = R4_ARG2; // source byte array const Register dataLen = R5_ARG3; // #bytes to process - const Register table = R6; // crc table address - -#ifdef VM_LITTLE_ENDIAN if (VM_Version::has_vpmsumb()) { const Register constants = R2; // constants address const Register bconstants = R8; // barret table address @@ -3321,7 +3351,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::ppc64::generate_load_crc_constants_addr(_masm, constants); StubRoutines::ppc64::generate_load_crc_barret_constants_addr(_masm, bconstants); - __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4); + __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4, true); BLOCK_COMMENT("return"); __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). @@ -3331,31 +3361,79 @@ class StubGenerator: public StubCodeGenerator { } else #endif { - const Register t0 = R2; - const Register t1 = R7; - const Register t2 = R8; - const Register t3 = R9; - const Register tc0 = R10; - const Register tc1 = R11; - const Register tc2 = R12; + StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); + generate_CRC_updateBytes(name, table, true); + } + + return start; + } + + + /** + * Arguments: + * + * Inputs: + * R3_ARG1 - int crc + * R4_ARG2 - byte* buf + * R5_ARG3 - int length (of buffer) + * + * scratch: + * R2, R6-R12 + * + * Ouput: + * R3_RET - int crc result + */ + // Compute CRC32C function. + address generate_CRC32C_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ function_entry(); // Remember stub start address (is rtn value). + + const Register table = R6; // crc table address + +#if 0 // no vector support yet for CRC32C +#ifdef VM_LITTLE_ENDIAN + // arguments to kernel_crc32: + const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. + const Register data = R4_ARG2; // source byte array + const Register dataLen = R5_ARG3; // #bytes to process + + if (VM_Version::has_vpmsumb()) { + const Register constants = R2; // constants address + const Register bconstants = R8; // barret table address + + const Register t0 = R9; + const Register t1 = R10; + const Register t2 = R11; + const Register t3 = R12; + const Register t4 = R7; BLOCK_COMMENT("Stub body {"); assert_different_registers(crc, data, dataLen, table); - StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); + StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table); + StubRoutines::ppc64::generate_load_crc32c_constants_addr(_masm, constants); + StubRoutines::ppc64::generate_load_crc32c_barret_constants_addr(_masm, bconstants); - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table); + __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4, false); BLOCK_COMMENT("return"); __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). __ blr(); BLOCK_COMMENT("} Stub body"); + } else +#endif +#endif + { + StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table); + generate_CRC_updateBytes(name, table, false); } return start; } + // Initialization void generate_initial() { // Generates all stubs and initializes the entry points @@ -3383,6 +3461,12 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_crc_table_adr = (address)StubRoutines::ppc64::_crc_table; StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); } + + // CRC32C Intrinsics. + if (UseCRC32CIntrinsics) { + StubRoutines::_crc32c_table_addr = (address)StubRoutines::ppc64::_crc32c_table; + StubRoutines::_updateBytesCRC32C = generate_CRC32C_updateBytes("CRC32C_updateBytes"); + } } void generate_all() { diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp index 5b5b2c270dd..dcda6be8a76 100644 --- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,13 +55,16 @@ class ppc64 { // CRC32 Intrinsics. static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; + static juint _crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; static juint* _constants; static juint* _barret_constants; public: // CRC32 Intrinsics. + static void generate_load_table_addr(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents); static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); + static void generate_load_crc32c_table_addr(MacroAssembler* masm, Register table); static void generate_load_crc_constants_addr(MacroAssembler* masm, Register table); static void generate_load_crc_barret_constants_addr(MacroAssembler* masm, Register table); static juint* generate_crc_constants(); diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp index 088d63a2f79..f5591669bcd 100644 --- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,11 @@ #define __ masm-> -// CRC32 Intrinsics. +// CRC32(C) Intrinsics. +void StubRoutines::ppc64::generate_load_crc32c_table_addr(MacroAssembler* masm, Register table) { + __ load_const_optimized(table, StubRoutines::_crc32c_table_addr, R0); +} + void StubRoutines::ppc64::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { __ load_const_optimized(table, StubRoutines::_crc_table_adr, R0); } @@ -347,441 +351,592 @@ juint* StubRoutines::ppc64::generate_crc_barret_constants() { * crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h */ juint StubRoutines::ppc64::_crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef CRC32_BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; + /* polyBits = 7976584769 0x00000001db710641L, shifted = 0xedb88320 */ + /* CRC32 table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32 table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U + /* 8 */ , 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U + /* 16 */ , 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U + /* 24 */ , 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U + /* 32 */ , 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU + /* 40 */ , 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U + /* 48 */ , 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU + /* 56 */ , 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU + /* 64 */ , 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U + /* 72 */ , 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U + /* 80 */ , 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U + /* 88 */ , 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U + /* 96 */ , 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU + /* 104 */ , 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U + /* 112 */ , 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU + /* 120 */ , 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU + /* 128 */ , 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U + /* 136 */ , 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U + /* 144 */ , 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U + /* 152 */ , 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U + /* 160 */ , 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU + /* 168 */ , 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U + /* 176 */ , 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU + /* 184 */ , 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU + /* 192 */ , 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U + /* 200 */ , 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U + /* 208 */ , 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U + /* 216 */ , 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U + /* 224 */ , 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU + /* 232 */ , 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U + /* 240 */ , 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU + /* 248 */ , 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU + } + #ifdef CRC32_BYFOUR + , + /* CRC32 table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, 0x7d77f445U, 0x565aa786U, 0x4f4196c7U + /* 8 */ , 0xc8d98a08U, 0xd1c2bb49U, 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, 0x87981ccfU + /* 16 */ , 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U + /* 24 */ , 0x821b9859U, 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, 0xd4413fdfU, 0xcd5a0e9eU + /* 32 */ , 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U + /* 40 */ , 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, 0x202a5aefU, 0x0b07092cU, 0x121c386dU + /* 48 */ , 0xdf4636f3U, 0xc65d07b2U, 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, 0x9007a034U + /* 56 */ , 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU + /* 64 */ , 0xf0794f05U, 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, 0xa623e883U, 0xbf38d9c2U + /* 72 */ , 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU + /* 80 */ , 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, 0xc7cca911U, 0xece1fad2U, 0xf5facb93U + /* 88 */ , 0x7262d75cU, 0x6b79e61dU, 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, 0x3d23419bU + /* 96 */ , 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U + /* 104 */ , 0xad24e1afU, 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, 0xfb7e4629U, 0xe2657768U + /* 112 */ , 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U + /* 120 */ , 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U + /* 128 */ , 0x3b83984bU, 0x2298a90aU, 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, 0x74c20e8cU + /* 136 */ , 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U + /* 144 */ , 0x71418a1aU, 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, 0x271b2d9cU, 0x3e001cddU + /* 152 */ , 0xb9980012U, 0xa0833153U, 0x8bae6290U, 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U + /* 160 */ , 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU + /* 168 */ , 0x66de36e1U, 0x7fc507a0U, 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, 0x299fa026U + /* 176 */ , 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU + /* 184 */ , 0x2c1c24b0U, 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, 0x7a468336U, 0x635db277U + /* 192 */ , 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U + /* 200 */ , 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U + /* 208 */ , 0x8138c51fU, 0x9823f45eU, 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, 0xce7953d8U + /* 216 */ , 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U + /* 224 */ , 0x5e7ef3ecU, 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, 0x0824546aU, 0x113f652bU + /* 232 */ , 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U + /* 240 */ , 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU + /* 248 */ , 0xdc656bb5U, 0xc57e5af4U, 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, 0x9324fd72U + } + , + /* CRC32 table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U + /* 8 */ , 0x0e1351b8U, 0x0fd13b8fU, 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, 0x0b5c473dU + /* 16 */ , 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U + /* 24 */ , 0x1235f2c8U, 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, 0x16b88e7aU, 0x177ae44dU + /* 32 */ , 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U + /* 40 */ , 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, 0x3095d5b3U, 0x32d36beaU, 0x331101ddU + /* 48 */ , 0x246be590U, 0x25a98fa7U, 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, 0x2124f315U + /* 56 */ , 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU + /* 64 */ , 0x709a8dc0U, 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, 0x7417f172U, 0x75d59b45U + /* 72 */ , 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU + /* 80 */ , 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, 0x6a77ec5bU, 0x68315202U, 0x69f33835U + /* 88 */ , 0x62af7f08U, 0x636d153fU, 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, 0x67e0698dU + /* 96 */ , 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U + /* 104 */ , 0x46c49a98U, 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, 0x4249e62aU, 0x438b8c1dU + /* 112 */ , 0x54f16850U, 0x55330267U, 0x5775bc3eU, 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U + /* 120 */ , 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU + /* 128 */ , 0xe1351b80U, 0xe0f771b7U, 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, 0xe47a0d05U + /* 136 */ , 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU + /* 144 */ , 0xfd13b8f0U, 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, 0xf99ec442U, 0xf85cae75U + /* 152 */ , 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU + /* 160 */ , 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U + /* 168 */ , 0xd76b0cd8U, 0xd6a966efU, 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, 0xd2241a5dU + /* 176 */ , 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U + /* 184 */ , 0xcb4dafa8U, 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, 0xcfc0d31aU, 0xce02b92dU + /* 192 */ , 0x91af9640U, 0x906dfc77U, 0x922b422eU, 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U + /* 200 */ , 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU + /* 208 */ , 0x8d893530U, 0x8c4b5f07U, 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, 0x88c623b5U + /* 216 */ , 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU + /* 224 */ , 0xa9e2d0a0U, 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, 0xad6fac12U, 0xacadc625U + /* 232 */ , 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU + /* 240 */ , 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U + /* 248 */ , 0xbbd72268U, 0xba15485fU, 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, 0xbe9834edU + } + , + /* CRC32 table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, 0x37def032U, 0x256b5fdcU, 0x9dd738b9U + /* 8 */ , 0xc5b428efU, 0x7d084f8aU, 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, 0x58631056U + /* 16 */ , 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U + /* 24 */ , 0x95ad7f70U, 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, 0xb0c620acU, 0x087a47c9U + /* 32 */ , 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U + /* 40 */ , 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, 0x525877e3U, 0x40edd80dU, 0xf851bf68U + /* 48 */ , 0xf02bf8a1U, 0x48979fc4U, 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, 0x6dfcc018U + /* 56 */ , 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U + /* 64 */ , 0x9b14583dU, 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, 0xbe7f07e1U, 0x06c36084U + /* 72 */ , 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU + /* 80 */ , 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, 0xfcd3ff90U, 0xee66507eU, 0x56da371bU + /* 88 */ , 0x0eb9274dU, 0xb6054028U, 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, 0x936e1ff4U + /* 96 */ , 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU + /* 104 */ , 0xfe92dfecU, 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, 0xdbf98030U, 0x6345e755U + /* 112 */ , 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U + /* 120 */ , 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, 0x99557841U, 0x8be0d7afU, 0x335cb0caU + /* 128 */ , 0xed59b63bU, 0x55e5d15eU, 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, 0x708e8e82U + /* 136 */ , 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU + /* 144 */ , 0xbd40e1a4U, 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, 0x982bbe78U, 0x2097d91dU + /* 152 */ , 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U + /* 160 */ , 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU + /* 168 */ , 0x88df31eaU, 0x3063568fU, 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, 0x15080953U + /* 176 */ , 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U + /* 184 */ , 0xd8c66675U, 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, 0xfdad39a9U, 0x45115eccU + /* 192 */ , 0x764dee06U, 0xcef18963U, 0xdc44268dU, 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU + /* 200 */ , 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, 0x842736dbU, 0x96929935U, 0x2e2efe50U + /* 208 */ , 0x2654b999U, 0x9ee8defcU, 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, 0xbb838120U + /* 216 */ , 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU + /* 224 */ , 0xd67f4138U, 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, 0xf3141ee4U, 0x4ba87981U + /* 232 */ , 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU + /* 240 */ , 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU + /* 248 */ , 0x43d23e48U, 0xfb6e592dU, 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, 0xde0506f1U + } + , + /* CRC32 table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x96300777U, 0x2c610eeeU, 0xba510999U, 0x19c46d07U, 0x8ff46a70U, 0x35a563e9U, 0xa395649eU + /* 8 */ , 0x3288db0eU, 0xa4b8dc79U, 0x1ee9d5e0U, 0x88d9d297U, 0x2b4cb609U, 0xbd7cb17eU, 0x072db8e7U, 0x911dbf90U + /* 16 */ , 0x6410b71dU, 0xf220b06aU, 0x4871b9f3U, 0xde41be84U, 0x7dd4da1aU, 0xebe4dd6dU, 0x51b5d4f4U, 0xc785d383U + /* 24 */ , 0x56986c13U, 0xc0a86b64U, 0x7af962fdU, 0xecc9658aU, 0x4f5c0114U, 0xd96c0663U, 0x633d0ffaU, 0xf50d088dU + /* 32 */ , 0xc8206e3bU, 0x5e10694cU, 0xe44160d5U, 0x727167a2U, 0xd1e4033cU, 0x47d4044bU, 0xfd850dd2U, 0x6bb50aa5U + /* 40 */ , 0xfaa8b535U, 0x6c98b242U, 0xd6c9bbdbU, 0x40f9bcacU, 0xe36cd832U, 0x755cdf45U, 0xcf0dd6dcU, 0x593dd1abU + /* 48 */ , 0xac30d926U, 0x3a00de51U, 0x8051d7c8U, 0x1661d0bfU, 0xb5f4b421U, 0x23c4b356U, 0x9995bacfU, 0x0fa5bdb8U + /* 56 */ , 0x9eb80228U, 0x0888055fU, 0xb2d90cc6U, 0x24e90bb1U, 0x877c6f2fU, 0x114c6858U, 0xab1d61c1U, 0x3d2d66b6U + /* 64 */ , 0x9041dc76U, 0x0671db01U, 0xbc20d298U, 0x2a10d5efU, 0x8985b171U, 0x1fb5b606U, 0xa5e4bf9fU, 0x33d4b8e8U + /* 72 */ , 0xa2c90778U, 0x34f9000fU, 0x8ea80996U, 0x18980ee1U, 0xbb0d6a7fU, 0x2d3d6d08U, 0x976c6491U, 0x015c63e6U + /* 80 */ , 0xf4516b6bU, 0x62616c1cU, 0xd8306585U, 0x4e0062f2U, 0xed95066cU, 0x7ba5011bU, 0xc1f40882U, 0x57c40ff5U + /* 88 */ , 0xc6d9b065U, 0x50e9b712U, 0xeab8be8bU, 0x7c88b9fcU, 0xdf1ddd62U, 0x492dda15U, 0xf37cd38cU, 0x654cd4fbU + /* 96 */ , 0x5861b24dU, 0xce51b53aU, 0x7400bca3U, 0xe230bbd4U, 0x41a5df4aU, 0xd795d83dU, 0x6dc4d1a4U, 0xfbf4d6d3U + /* 104 */ , 0x6ae96943U, 0xfcd96e34U, 0x468867adU, 0xd0b860daU, 0x732d0444U, 0xe51d0333U, 0x5f4c0aaaU, 0xc97c0dddU + /* 112 */ , 0x3c710550U, 0xaa410227U, 0x10100bbeU, 0x86200cc9U, 0x25b56857U, 0xb3856f20U, 0x09d466b9U, 0x9fe461ceU + /* 120 */ , 0x0ef9de5eU, 0x98c9d929U, 0x2298d0b0U, 0xb4a8d7c7U, 0x173db359U, 0x810db42eU, 0x3b5cbdb7U, 0xad6cbac0U + /* 128 */ , 0x2083b8edU, 0xb6b3bf9aU, 0x0ce2b603U, 0x9ad2b174U, 0x3947d5eaU, 0xaf77d29dU, 0x1526db04U, 0x8316dc73U + /* 136 */ , 0x120b63e3U, 0x843b6494U, 0x3e6a6d0dU, 0xa85a6a7aU, 0x0bcf0ee4U, 0x9dff0993U, 0x27ae000aU, 0xb19e077dU + /* 144 */ , 0x44930ff0U, 0xd2a30887U, 0x68f2011eU, 0xfec20669U, 0x5d5762f7U, 0xcb676580U, 0x71366c19U, 0xe7066b6eU + /* 152 */ , 0x761bd4feU, 0xe02bd389U, 0x5a7ada10U, 0xcc4add67U, 0x6fdfb9f9U, 0xf9efbe8eU, 0x43beb717U, 0xd58eb060U + /* 160 */ , 0xe8a3d6d6U, 0x7e93d1a1U, 0xc4c2d838U, 0x52f2df4fU, 0xf167bbd1U, 0x6757bca6U, 0xdd06b53fU, 0x4b36b248U + /* 168 */ , 0xda2b0dd8U, 0x4c1b0aafU, 0xf64a0336U, 0x607a0441U, 0xc3ef60dfU, 0x55df67a8U, 0xef8e6e31U, 0x79be6946U + /* 176 */ , 0x8cb361cbU, 0x1a8366bcU, 0xa0d26f25U, 0x36e26852U, 0x95770cccU, 0x03470bbbU, 0xb9160222U, 0x2f260555U + /* 184 */ , 0xbe3bbac5U, 0x280bbdb2U, 0x925ab42bU, 0x046ab35cU, 0xa7ffd7c2U, 0x31cfd0b5U, 0x8b9ed92cU, 0x1daede5bU + /* 192 */ , 0xb0c2649bU, 0x26f263ecU, 0x9ca36a75U, 0x0a936d02U, 0xa906099cU, 0x3f360eebU, 0x85670772U, 0x13570005U + /* 200 */ , 0x824abf95U, 0x147ab8e2U, 0xae2bb17bU, 0x381bb60cU, 0x9b8ed292U, 0x0dbed5e5U, 0xb7efdc7cU, 0x21dfdb0bU + /* 208 */ , 0xd4d2d386U, 0x42e2d4f1U, 0xf8b3dd68U, 0x6e83da1fU, 0xcd16be81U, 0x5b26b9f6U, 0xe177b06fU, 0x7747b718U + /* 216 */ , 0xe65a0888U, 0x706a0fffU, 0xca3b0666U, 0x5c0b0111U, 0xff9e658fU, 0x69ae62f8U, 0xd3ff6b61U, 0x45cf6c16U + /* 224 */ , 0x78e20aa0U, 0xeed20dd7U, 0x5483044eU, 0xc2b30339U, 0x612667a7U, 0xf71660d0U, 0x4d476949U, 0xdb776e3eU + /* 232 */ , 0x4a6ad1aeU, 0xdc5ad6d9U, 0x660bdf40U, 0xf03bd837U, 0x53aebca9U, 0xc59ebbdeU, 0x7fcfb247U, 0xe9ffb530U + /* 240 */ , 0x1cf2bdbdU, 0x8ac2bacaU, 0x3093b353U, 0xa6a3b424U, 0x0536d0baU, 0x9306d7cdU, 0x2957de54U, 0xbf67d923U + /* 248 */ , 0x2e7a66b3U, 0xb84a61c4U, 0x021b685dU, 0x942b6f2aU, 0x37be0bb4U, 0xa18e0cc3U, 0x1bdf055aU, 0x8def022dU + } + , + /* CRC32 table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x41311b19U, 0x82623632U, 0xc3532d2bU, 0x04c56c64U, 0x45f4777dU, 0x86a75a56U, 0xc796414fU + /* 8 */ , 0x088ad9c8U, 0x49bbc2d1U, 0x8ae8effaU, 0xcbd9f4e3U, 0x0c4fb5acU, 0x4d7eaeb5U, 0x8e2d839eU, 0xcf1c9887U + /* 16 */ , 0x5112c24aU, 0x1023d953U, 0xd370f478U, 0x9241ef61U, 0x55d7ae2eU, 0x14e6b537U, 0xd7b5981cU, 0x96848305U + /* 24 */ , 0x59981b82U, 0x18a9009bU, 0xdbfa2db0U, 0x9acb36a9U, 0x5d5d77e6U, 0x1c6c6cffU, 0xdf3f41d4U, 0x9e0e5acdU + /* 32 */ , 0xa2248495U, 0xe3159f8cU, 0x2046b2a7U, 0x6177a9beU, 0xa6e1e8f1U, 0xe7d0f3e8U, 0x2483dec3U, 0x65b2c5daU + /* 40 */ , 0xaaae5d5dU, 0xeb9f4644U, 0x28cc6b6fU, 0x69fd7076U, 0xae6b3139U, 0xef5a2a20U, 0x2c09070bU, 0x6d381c12U + /* 48 */ , 0xf33646dfU, 0xb2075dc6U, 0x715470edU, 0x30656bf4U, 0xf7f32abbU, 0xb6c231a2U, 0x75911c89U, 0x34a00790U + /* 56 */ , 0xfbbc9f17U, 0xba8d840eU, 0x79dea925U, 0x38efb23cU, 0xff79f373U, 0xbe48e86aU, 0x7d1bc541U, 0x3c2ade58U + /* 64 */ , 0x054f79f0U, 0x447e62e9U, 0x872d4fc2U, 0xc61c54dbU, 0x018a1594U, 0x40bb0e8dU, 0x83e823a6U, 0xc2d938bfU + /* 72 */ , 0x0dc5a038U, 0x4cf4bb21U, 0x8fa7960aU, 0xce968d13U, 0x0900cc5cU, 0x4831d745U, 0x8b62fa6eU, 0xca53e177U + /* 80 */ , 0x545dbbbaU, 0x156ca0a3U, 0xd63f8d88U, 0x970e9691U, 0x5098d7deU, 0x11a9ccc7U, 0xd2fae1ecU, 0x93cbfaf5U + /* 88 */ , 0x5cd76272U, 0x1de6796bU, 0xdeb55440U, 0x9f844f59U, 0x58120e16U, 0x1923150fU, 0xda703824U, 0x9b41233dU + /* 96 */ , 0xa76bfd65U, 0xe65ae67cU, 0x2509cb57U, 0x6438d04eU, 0xa3ae9101U, 0xe29f8a18U, 0x21cca733U, 0x60fdbc2aU + /* 104 */ , 0xafe124adU, 0xeed03fb4U, 0x2d83129fU, 0x6cb20986U, 0xab2448c9U, 0xea1553d0U, 0x29467efbU, 0x687765e2U + /* 112 */ , 0xf6793f2fU, 0xb7482436U, 0x741b091dU, 0x352a1204U, 0xf2bc534bU, 0xb38d4852U, 0x70de6579U, 0x31ef7e60U + /* 120 */ , 0xfef3e6e7U, 0xbfc2fdfeU, 0x7c91d0d5U, 0x3da0cbccU, 0xfa368a83U, 0xbb07919aU, 0x7854bcb1U, 0x3965a7a8U + /* 128 */ , 0x4b98833bU, 0x0aa99822U, 0xc9fab509U, 0x88cbae10U, 0x4f5def5fU, 0x0e6cf446U, 0xcd3fd96dU, 0x8c0ec274U + /* 136 */ , 0x43125af3U, 0x022341eaU, 0xc1706cc1U, 0x804177d8U, 0x47d73697U, 0x06e62d8eU, 0xc5b500a5U, 0x84841bbcU + /* 144 */ , 0x1a8a4171U, 0x5bbb5a68U, 0x98e87743U, 0xd9d96c5aU, 0x1e4f2d15U, 0x5f7e360cU, 0x9c2d1b27U, 0xdd1c003eU + /* 152 */ , 0x120098b9U, 0x533183a0U, 0x9062ae8bU, 0xd153b592U, 0x16c5f4ddU, 0x57f4efc4U, 0x94a7c2efU, 0xd596d9f6U + /* 160 */ , 0xe9bc07aeU, 0xa88d1cb7U, 0x6bde319cU, 0x2aef2a85U, 0xed796bcaU, 0xac4870d3U, 0x6f1b5df8U, 0x2e2a46e1U + /* 168 */ , 0xe136de66U, 0xa007c57fU, 0x6354e854U, 0x2265f34dU, 0xe5f3b202U, 0xa4c2a91bU, 0x67918430U, 0x26a09f29U + /* 176 */ , 0xb8aec5e4U, 0xf99fdefdU, 0x3accf3d6U, 0x7bfde8cfU, 0xbc6ba980U, 0xfd5ab299U, 0x3e099fb2U, 0x7f3884abU + /* 184 */ , 0xb0241c2cU, 0xf1150735U, 0x32462a1eU, 0x73773107U, 0xb4e17048U, 0xf5d06b51U, 0x3683467aU, 0x77b25d63U + /* 192 */ , 0x4ed7facbU, 0x0fe6e1d2U, 0xccb5ccf9U, 0x8d84d7e0U, 0x4a1296afU, 0x0b238db6U, 0xc870a09dU, 0x8941bb84U + /* 200 */ , 0x465d2303U, 0x076c381aU, 0xc43f1531U, 0x850e0e28U, 0x42984f67U, 0x03a9547eU, 0xc0fa7955U, 0x81cb624cU + /* 208 */ , 0x1fc53881U, 0x5ef42398U, 0x9da70eb3U, 0xdc9615aaU, 0x1b0054e5U, 0x5a314ffcU, 0x996262d7U, 0xd85379ceU + /* 216 */ , 0x174fe149U, 0x567efa50U, 0x952dd77bU, 0xd41ccc62U, 0x138a8d2dU, 0x52bb9634U, 0x91e8bb1fU, 0xd0d9a006U + /* 224 */ , 0xecf37e5eU, 0xadc26547U, 0x6e91486cU, 0x2fa05375U, 0xe836123aU, 0xa9070923U, 0x6a542408U, 0x2b653f11U + /* 232 */ , 0xe479a796U, 0xa548bc8fU, 0x661b91a4U, 0x272a8abdU, 0xe0bccbf2U, 0xa18dd0ebU, 0x62defdc0U, 0x23efe6d9U + /* 240 */ , 0xbde1bc14U, 0xfcd0a70dU, 0x3f838a26U, 0x7eb2913fU, 0xb924d070U, 0xf815cb69U, 0x3b46e642U, 0x7a77fd5bU + /* 248 */ , 0xb56b65dcU, 0xf45a7ec5U, 0x370953eeU, 0x763848f7U, 0xb1ae09b8U, 0xf09f12a1U, 0x33cc3f8aU, 0x72fd2493U + } + , + /* CRC32 table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x376ac201U, 0x6ed48403U, 0x59be4602U, 0xdca80907U, 0xebc2cb06U, 0xb27c8d04U, 0x85164f05U + /* 8 */ , 0xb851130eU, 0x8f3bd10fU, 0xd685970dU, 0xe1ef550cU, 0x64f91a09U, 0x5393d808U, 0x0a2d9e0aU, 0x3d475c0bU + /* 16 */ , 0x70a3261cU, 0x47c9e41dU, 0x1e77a21fU, 0x291d601eU, 0xac0b2f1bU, 0x9b61ed1aU, 0xc2dfab18U, 0xf5b56919U + /* 24 */ , 0xc8f23512U, 0xff98f713U, 0xa626b111U, 0x914c7310U, 0x145a3c15U, 0x2330fe14U, 0x7a8eb816U, 0x4de47a17U + /* 32 */ , 0xe0464d38U, 0xd72c8f39U, 0x8e92c93bU, 0xb9f80b3aU, 0x3cee443fU, 0x0b84863eU, 0x523ac03cU, 0x6550023dU + /* 40 */ , 0x58175e36U, 0x6f7d9c37U, 0x36c3da35U, 0x01a91834U, 0x84bf5731U, 0xb3d59530U, 0xea6bd332U, 0xdd011133U + /* 48 */ , 0x90e56b24U, 0xa78fa925U, 0xfe31ef27U, 0xc95b2d26U, 0x4c4d6223U, 0x7b27a022U, 0x2299e620U, 0x15f32421U + /* 56 */ , 0x28b4782aU, 0x1fdeba2bU, 0x4660fc29U, 0x710a3e28U, 0xf41c712dU, 0xc376b32cU, 0x9ac8f52eU, 0xada2372fU + /* 64 */ , 0xc08d9a70U, 0xf7e75871U, 0xae591e73U, 0x9933dc72U, 0x1c259377U, 0x2b4f5176U, 0x72f11774U, 0x459bd575U + /* 72 */ , 0x78dc897eU, 0x4fb64b7fU, 0x16080d7dU, 0x2162cf7cU, 0xa4748079U, 0x931e4278U, 0xcaa0047aU, 0xfdcac67bU + /* 80 */ , 0xb02ebc6cU, 0x87447e6dU, 0xdefa386fU, 0xe990fa6eU, 0x6c86b56bU, 0x5bec776aU, 0x02523168U, 0x3538f369U + /* 88 */ , 0x087faf62U, 0x3f156d63U, 0x66ab2b61U, 0x51c1e960U, 0xd4d7a665U, 0xe3bd6464U, 0xba032266U, 0x8d69e067U + /* 96 */ , 0x20cbd748U, 0x17a11549U, 0x4e1f534bU, 0x7975914aU, 0xfc63de4fU, 0xcb091c4eU, 0x92b75a4cU, 0xa5dd984dU + /* 104 */ , 0x989ac446U, 0xaff00647U, 0xf64e4045U, 0xc1248244U, 0x4432cd41U, 0x73580f40U, 0x2ae64942U, 0x1d8c8b43U + /* 112 */ , 0x5068f154U, 0x67023355U, 0x3ebc7557U, 0x09d6b756U, 0x8cc0f853U, 0xbbaa3a52U, 0xe2147c50U, 0xd57ebe51U + /* 120 */ , 0xe839e25aU, 0xdf53205bU, 0x86ed6659U, 0xb187a458U, 0x3491eb5dU, 0x03fb295cU, 0x5a456f5eU, 0x6d2fad5fU + /* 128 */ , 0x801b35e1U, 0xb771f7e0U, 0xeecfb1e2U, 0xd9a573e3U, 0x5cb33ce6U, 0x6bd9fee7U, 0x3267b8e5U, 0x050d7ae4U + /* 136 */ , 0x384a26efU, 0x0f20e4eeU, 0x569ea2ecU, 0x61f460edU, 0xe4e22fe8U, 0xd388ede9U, 0x8a36abebU, 0xbd5c69eaU + /* 144 */ , 0xf0b813fdU, 0xc7d2d1fcU, 0x9e6c97feU, 0xa90655ffU, 0x2c101afaU, 0x1b7ad8fbU, 0x42c49ef9U, 0x75ae5cf8U + /* 152 */ , 0x48e900f3U, 0x7f83c2f2U, 0x263d84f0U, 0x115746f1U, 0x944109f4U, 0xa32bcbf5U, 0xfa958df7U, 0xcdff4ff6U + /* 160 */ , 0x605d78d9U, 0x5737bad8U, 0x0e89fcdaU, 0x39e33edbU, 0xbcf571deU, 0x8b9fb3dfU, 0xd221f5ddU, 0xe54b37dcU + /* 168 */ , 0xd80c6bd7U, 0xef66a9d6U, 0xb6d8efd4U, 0x81b22dd5U, 0x04a462d0U, 0x33cea0d1U, 0x6a70e6d3U, 0x5d1a24d2U + /* 176 */ , 0x10fe5ec5U, 0x27949cc4U, 0x7e2adac6U, 0x494018c7U, 0xcc5657c2U, 0xfb3c95c3U, 0xa282d3c1U, 0x95e811c0U + /* 184 */ , 0xa8af4dcbU, 0x9fc58fcaU, 0xc67bc9c8U, 0xf1110bc9U, 0x740744ccU, 0x436d86cdU, 0x1ad3c0cfU, 0x2db902ceU + /* 192 */ , 0x4096af91U, 0x77fc6d90U, 0x2e422b92U, 0x1928e993U, 0x9c3ea696U, 0xab546497U, 0xf2ea2295U, 0xc580e094U + /* 200 */ , 0xf8c7bc9fU, 0xcfad7e9eU, 0x9613389cU, 0xa179fa9dU, 0x246fb598U, 0x13057799U, 0x4abb319bU, 0x7dd1f39aU + /* 208 */ , 0x3035898dU, 0x075f4b8cU, 0x5ee10d8eU, 0x698bcf8fU, 0xec9d808aU, 0xdbf7428bU, 0x82490489U, 0xb523c688U + /* 216 */ , 0x88649a83U, 0xbf0e5882U, 0xe6b01e80U, 0xd1dadc81U, 0x54cc9384U, 0x63a65185U, 0x3a181787U, 0x0d72d586U + /* 224 */ , 0xa0d0e2a9U, 0x97ba20a8U, 0xce0466aaU, 0xf96ea4abU, 0x7c78ebaeU, 0x4b1229afU, 0x12ac6fadU, 0x25c6adacU + /* 232 */ , 0x1881f1a7U, 0x2feb33a6U, 0x765575a4U, 0x413fb7a5U, 0xc429f8a0U, 0xf3433aa1U, 0xaafd7ca3U, 0x9d97bea2U + /* 240 */ , 0xd073c4b5U, 0xe71906b4U, 0xbea740b6U, 0x89cd82b7U, 0x0cdbcdb2U, 0x3bb10fb3U, 0x620f49b1U, 0x55658bb0U + /* 248 */ , 0x6822d7bbU, 0x5f4815baU, 0x06f653b8U, 0x319c91b9U, 0xb48adebcU, 0x83e01cbdU, 0xda5e5abfU, 0xed3498beU + } + , + /* CRC32 table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x6567bcb8U, 0x8bc809aaU, 0xeeafb512U, 0x5797628fU, 0x32f0de37U, 0xdc5f6b25U, 0xb938d79dU + /* 8 */ , 0xef28b4c5U, 0x8a4f087dU, 0x64e0bd6fU, 0x018701d7U, 0xb8bfd64aU, 0xddd86af2U, 0x3377dfe0U, 0x56106358U + /* 16 */ , 0x9f571950U, 0xfa30a5e8U, 0x149f10faU, 0x71f8ac42U, 0xc8c07bdfU, 0xada7c767U, 0x43087275U, 0x266fcecdU + /* 24 */ , 0x707fad95U, 0x1518112dU, 0xfbb7a43fU, 0x9ed01887U, 0x27e8cf1aU, 0x428f73a2U, 0xac20c6b0U, 0xc9477a08U + /* 32 */ , 0x3eaf32a0U, 0x5bc88e18U, 0xb5673b0aU, 0xd00087b2U, 0x6938502fU, 0x0c5fec97U, 0xe2f05985U, 0x8797e53dU + /* 40 */ , 0xd1878665U, 0xb4e03addU, 0x5a4f8fcfU, 0x3f283377U, 0x8610e4eaU, 0xe3775852U, 0x0dd8ed40U, 0x68bf51f8U + /* 48 */ , 0xa1f82bf0U, 0xc49f9748U, 0x2a30225aU, 0x4f579ee2U, 0xf66f497fU, 0x9308f5c7U, 0x7da740d5U, 0x18c0fc6dU + /* 56 */ , 0x4ed09f35U, 0x2bb7238dU, 0xc518969fU, 0xa07f2a27U, 0x1947fdbaU, 0x7c204102U, 0x928ff410U, 0xf7e848a8U + /* 64 */ , 0x3d58149bU, 0x583fa823U, 0xb6901d31U, 0xd3f7a189U, 0x6acf7614U, 0x0fa8caacU, 0xe1077fbeU, 0x8460c306U + /* 72 */ , 0xd270a05eU, 0xb7171ce6U, 0x59b8a9f4U, 0x3cdf154cU, 0x85e7c2d1U, 0xe0807e69U, 0x0e2fcb7bU, 0x6b4877c3U + /* 80 */ , 0xa20f0dcbU, 0xc768b173U, 0x29c70461U, 0x4ca0b8d9U, 0xf5986f44U, 0x90ffd3fcU, 0x7e5066eeU, 0x1b37da56U + /* 88 */ , 0x4d27b90eU, 0x284005b6U, 0xc6efb0a4U, 0xa3880c1cU, 0x1ab0db81U, 0x7fd76739U, 0x9178d22bU, 0xf41f6e93U + /* 96 */ , 0x03f7263bU, 0x66909a83U, 0x883f2f91U, 0xed589329U, 0x546044b4U, 0x3107f80cU, 0xdfa84d1eU, 0xbacff1a6U + /* 104 */ , 0xecdf92feU, 0x89b82e46U, 0x67179b54U, 0x027027ecU, 0xbb48f071U, 0xde2f4cc9U, 0x3080f9dbU, 0x55e74563U + /* 112 */ , 0x9ca03f6bU, 0xf9c783d3U, 0x176836c1U, 0x720f8a79U, 0xcb375de4U, 0xae50e15cU, 0x40ff544eU, 0x2598e8f6U + /* 120 */ , 0x73888baeU, 0x16ef3716U, 0xf8408204U, 0x9d273ebcU, 0x241fe921U, 0x41785599U, 0xafd7e08bU, 0xcab05c33U + /* 128 */ , 0x3bb659edU, 0x5ed1e555U, 0xb07e5047U, 0xd519ecffU, 0x6c213b62U, 0x094687daU, 0xe7e932c8U, 0x828e8e70U + /* 136 */ , 0xd49eed28U, 0xb1f95190U, 0x5f56e482U, 0x3a31583aU, 0x83098fa7U, 0xe66e331fU, 0x08c1860dU, 0x6da63ab5U + /* 144 */ , 0xa4e140bdU, 0xc186fc05U, 0x2f294917U, 0x4a4ef5afU, 0xf3762232U, 0x96119e8aU, 0x78be2b98U, 0x1dd99720U + /* 152 */ , 0x4bc9f478U, 0x2eae48c0U, 0xc001fdd2U, 0xa566416aU, 0x1c5e96f7U, 0x79392a4fU, 0x97969f5dU, 0xf2f123e5U + /* 160 */ , 0x05196b4dU, 0x607ed7f5U, 0x8ed162e7U, 0xebb6de5fU, 0x528e09c2U, 0x37e9b57aU, 0xd9460068U, 0xbc21bcd0U + /* 168 */ , 0xea31df88U, 0x8f566330U, 0x61f9d622U, 0x049e6a9aU, 0xbda6bd07U, 0xd8c101bfU, 0x366eb4adU, 0x53090815U + /* 176 */ , 0x9a4e721dU, 0xff29cea5U, 0x11867bb7U, 0x74e1c70fU, 0xcdd91092U, 0xa8beac2aU, 0x46111938U, 0x2376a580U + /* 184 */ , 0x7566c6d8U, 0x10017a60U, 0xfeaecf72U, 0x9bc973caU, 0x22f1a457U, 0x479618efU, 0xa939adfdU, 0xcc5e1145U + /* 192 */ , 0x06ee4d76U, 0x6389f1ceU, 0x8d2644dcU, 0xe841f864U, 0x51792ff9U, 0x341e9341U, 0xdab12653U, 0xbfd69aebU + /* 200 */ , 0xe9c6f9b3U, 0x8ca1450bU, 0x620ef019U, 0x07694ca1U, 0xbe519b3cU, 0xdb362784U, 0x35999296U, 0x50fe2e2eU + /* 208 */ , 0x99b95426U, 0xfcdee89eU, 0x12715d8cU, 0x7716e134U, 0xce2e36a9U, 0xab498a11U, 0x45e63f03U, 0x208183bbU + /* 216 */ , 0x7691e0e3U, 0x13f65c5bU, 0xfd59e949U, 0x983e55f1U, 0x2106826cU, 0x44613ed4U, 0xaace8bc6U, 0xcfa9377eU + /* 224 */ , 0x38417fd6U, 0x5d26c36eU, 0xb389767cU, 0xd6eecac4U, 0x6fd61d59U, 0x0ab1a1e1U, 0xe41e14f3U, 0x8179a84bU + /* 232 */ , 0xd769cb13U, 0xb20e77abU, 0x5ca1c2b9U, 0x39c67e01U, 0x80fea99cU, 0xe5991524U, 0x0b36a036U, 0x6e511c8eU + /* 240 */ , 0xa7166686U, 0xc271da3eU, 0x2cde6f2cU, 0x49b9d394U, 0xf0810409U, 0x95e6b8b1U, 0x7b490da3U, 0x1e2eb11bU + /* 248 */ , 0x483ed243U, 0x2d596efbU, 0xc3f6dbe9U, 0xa6916751U, 0x1fa9b0ccU, 0x7ace0c74U, 0x9461b966U, 0xf10605deU + } + #endif + }; + +juint StubRoutines::ppc64::_crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { + /* polyBits = 4394350321 0x0000000105ec76f1L, shifted = 0x82f63b78 */ + /* CRC32C table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32C table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xf26b8303U, 0xe13b70f7U, 0x1350f3f4U, 0xc79a971fU, 0x35f1141cU, 0x26a1e7e8U, 0xd4ca64ebU + /* 8 */ , 0x8ad958cfU, 0x78b2dbccU, 0x6be22838U, 0x9989ab3bU, 0x4d43cfd0U, 0xbf284cd3U, 0xac78bf27U, 0x5e133c24U + /* 16 */ , 0x105ec76fU, 0xe235446cU, 0xf165b798U, 0x030e349bU, 0xd7c45070U, 0x25afd373U, 0x36ff2087U, 0xc494a384U + /* 24 */ , 0x9a879fa0U, 0x68ec1ca3U, 0x7bbcef57U, 0x89d76c54U, 0x5d1d08bfU, 0xaf768bbcU, 0xbc267848U, 0x4e4dfb4bU + /* 32 */ , 0x20bd8edeU, 0xd2d60dddU, 0xc186fe29U, 0x33ed7d2aU, 0xe72719c1U, 0x154c9ac2U, 0x061c6936U, 0xf477ea35U + /* 40 */ , 0xaa64d611U, 0x580f5512U, 0x4b5fa6e6U, 0xb93425e5U, 0x6dfe410eU, 0x9f95c20dU, 0x8cc531f9U, 0x7eaeb2faU + /* 48 */ , 0x30e349b1U, 0xc288cab2U, 0xd1d83946U, 0x23b3ba45U, 0xf779deaeU, 0x05125dadU, 0x1642ae59U, 0xe4292d5aU + /* 56 */ , 0xba3a117eU, 0x4851927dU, 0x5b016189U, 0xa96ae28aU, 0x7da08661U, 0x8fcb0562U, 0x9c9bf696U, 0x6ef07595U + /* 64 */ , 0x417b1dbcU, 0xb3109ebfU, 0xa0406d4bU, 0x522bee48U, 0x86e18aa3U, 0x748a09a0U, 0x67dafa54U, 0x95b17957U + /* 72 */ , 0xcba24573U, 0x39c9c670U, 0x2a993584U, 0xd8f2b687U, 0x0c38d26cU, 0xfe53516fU, 0xed03a29bU, 0x1f682198U + /* 80 */ , 0x5125dad3U, 0xa34e59d0U, 0xb01eaa24U, 0x42752927U, 0x96bf4dccU, 0x64d4cecfU, 0x77843d3bU, 0x85efbe38U + /* 88 */ , 0xdbfc821cU, 0x2997011fU, 0x3ac7f2ebU, 0xc8ac71e8U, 0x1c661503U, 0xee0d9600U, 0xfd5d65f4U, 0x0f36e6f7U + /* 96 */ , 0x61c69362U, 0x93ad1061U, 0x80fde395U, 0x72966096U, 0xa65c047dU, 0x5437877eU, 0x4767748aU, 0xb50cf789U + /* 104 */ , 0xeb1fcbadU, 0x197448aeU, 0x0a24bb5aU, 0xf84f3859U, 0x2c855cb2U, 0xdeeedfb1U, 0xcdbe2c45U, 0x3fd5af46U + /* 112 */ , 0x7198540dU, 0x83f3d70eU, 0x90a324faU, 0x62c8a7f9U, 0xb602c312U, 0x44694011U, 0x5739b3e5U, 0xa55230e6U + /* 120 */ , 0xfb410cc2U, 0x092a8fc1U, 0x1a7a7c35U, 0xe811ff36U, 0x3cdb9bddU, 0xceb018deU, 0xdde0eb2aU, 0x2f8b6829U + /* 128 */ , 0x82f63b78U, 0x709db87bU, 0x63cd4b8fU, 0x91a6c88cU, 0x456cac67U, 0xb7072f64U, 0xa457dc90U, 0x563c5f93U + /* 136 */ , 0x082f63b7U, 0xfa44e0b4U, 0xe9141340U, 0x1b7f9043U, 0xcfb5f4a8U, 0x3dde77abU, 0x2e8e845fU, 0xdce5075cU + /* 144 */ , 0x92a8fc17U, 0x60c37f14U, 0x73938ce0U, 0x81f80fe3U, 0x55326b08U, 0xa759e80bU, 0xb4091bffU, 0x466298fcU + /* 152 */ , 0x1871a4d8U, 0xea1a27dbU, 0xf94ad42fU, 0x0b21572cU, 0xdfeb33c7U, 0x2d80b0c4U, 0x3ed04330U, 0xccbbc033U + /* 160 */ , 0xa24bb5a6U, 0x502036a5U, 0x4370c551U, 0xb11b4652U, 0x65d122b9U, 0x97baa1baU, 0x84ea524eU, 0x7681d14dU + /* 168 */ , 0x2892ed69U, 0xdaf96e6aU, 0xc9a99d9eU, 0x3bc21e9dU, 0xef087a76U, 0x1d63f975U, 0x0e330a81U, 0xfc588982U + /* 176 */ , 0xb21572c9U, 0x407ef1caU, 0x532e023eU, 0xa145813dU, 0x758fe5d6U, 0x87e466d5U, 0x94b49521U, 0x66df1622U + /* 184 */ , 0x38cc2a06U, 0xcaa7a905U, 0xd9f75af1U, 0x2b9cd9f2U, 0xff56bd19U, 0x0d3d3e1aU, 0x1e6dcdeeU, 0xec064eedU + /* 192 */ , 0xc38d26c4U, 0x31e6a5c7U, 0x22b65633U, 0xd0ddd530U, 0x0417b1dbU, 0xf67c32d8U, 0xe52cc12cU, 0x1747422fU + /* 200 */ , 0x49547e0bU, 0xbb3ffd08U, 0xa86f0efcU, 0x5a048dffU, 0x8ecee914U, 0x7ca56a17U, 0x6ff599e3U, 0x9d9e1ae0U + /* 208 */ , 0xd3d3e1abU, 0x21b862a8U, 0x32e8915cU, 0xc083125fU, 0x144976b4U, 0xe622f5b7U, 0xf5720643U, 0x07198540U + /* 216 */ , 0x590ab964U, 0xab613a67U, 0xb831c993U, 0x4a5a4a90U, 0x9e902e7bU, 0x6cfbad78U, 0x7fab5e8cU, 0x8dc0dd8fU + /* 224 */ , 0xe330a81aU, 0x115b2b19U, 0x020bd8edU, 0xf0605beeU, 0x24aa3f05U, 0xd6c1bc06U, 0xc5914ff2U, 0x37faccf1U + /* 232 */ , 0x69e9f0d5U, 0x9b8273d6U, 0x88d28022U, 0x7ab90321U, 0xae7367caU, 0x5c18e4c9U, 0x4f48173dU, 0xbd23943eU + /* 240 */ , 0xf36e6f75U, 0x0105ec76U, 0x12551f82U, 0xe03e9c81U, 0x34f4f86aU, 0xc69f7b69U, 0xd5cf889dU, 0x27a40b9eU + /* 248 */ , 0x79b737baU, 0x8bdcb4b9U, 0x988c474dU, 0x6ae7c44eU, 0xbe2da0a5U, 0x4c4623a6U, 0x5f16d052U, 0xad7d5351U + } + #ifdef CRC32_BYFOUR + , + /* CRC32C table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x13a29877U, 0x274530eeU, 0x34e7a899U, 0x4e8a61dcU, 0x5d28f9abU, 0x69cf5132U, 0x7a6dc945U + /* 8 */ , 0x9d14c3b8U, 0x8eb65bcfU, 0xba51f356U, 0xa9f36b21U, 0xd39ea264U, 0xc03c3a13U, 0xf4db928aU, 0xe7790afdU + /* 16 */ , 0x3fc5f181U, 0x2c6769f6U, 0x1880c16fU, 0x0b225918U, 0x714f905dU, 0x62ed082aU, 0x560aa0b3U, 0x45a838c4U + /* 24 */ , 0xa2d13239U, 0xb173aa4eU, 0x859402d7U, 0x96369aa0U, 0xec5b53e5U, 0xfff9cb92U, 0xcb1e630bU, 0xd8bcfb7cU + /* 32 */ , 0x7f8be302U, 0x6c297b75U, 0x58ced3ecU, 0x4b6c4b9bU, 0x310182deU, 0x22a31aa9U, 0x1644b230U, 0x05e62a47U + /* 40 */ , 0xe29f20baU, 0xf13db8cdU, 0xc5da1054U, 0xd6788823U, 0xac154166U, 0xbfb7d911U, 0x8b507188U, 0x98f2e9ffU + /* 48 */ , 0x404e1283U, 0x53ec8af4U, 0x670b226dU, 0x74a9ba1aU, 0x0ec4735fU, 0x1d66eb28U, 0x298143b1U, 0x3a23dbc6U + /* 56 */ , 0xdd5ad13bU, 0xcef8494cU, 0xfa1fe1d5U, 0xe9bd79a2U, 0x93d0b0e7U, 0x80722890U, 0xb4958009U, 0xa737187eU + /* 64 */ , 0xff17c604U, 0xecb55e73U, 0xd852f6eaU, 0xcbf06e9dU, 0xb19da7d8U, 0xa23f3fafU, 0x96d89736U, 0x857a0f41U + /* 72 */ , 0x620305bcU, 0x71a19dcbU, 0x45463552U, 0x56e4ad25U, 0x2c896460U, 0x3f2bfc17U, 0x0bcc548eU, 0x186eccf9U + /* 80 */ , 0xc0d23785U, 0xd370aff2U, 0xe797076bU, 0xf4359f1cU, 0x8e585659U, 0x9dface2eU, 0xa91d66b7U, 0xbabffec0U + /* 88 */ , 0x5dc6f43dU, 0x4e646c4aU, 0x7a83c4d3U, 0x69215ca4U, 0x134c95e1U, 0x00ee0d96U, 0x3409a50fU, 0x27ab3d78U + /* 96 */ , 0x809c2506U, 0x933ebd71U, 0xa7d915e8U, 0xb47b8d9fU, 0xce1644daU, 0xddb4dcadU, 0xe9537434U, 0xfaf1ec43U + /* 104 */ , 0x1d88e6beU, 0x0e2a7ec9U, 0x3acdd650U, 0x296f4e27U, 0x53028762U, 0x40a01f15U, 0x7447b78cU, 0x67e52ffbU + /* 112 */ , 0xbf59d487U, 0xacfb4cf0U, 0x981ce469U, 0x8bbe7c1eU, 0xf1d3b55bU, 0xe2712d2cU, 0xd69685b5U, 0xc5341dc2U + /* 120 */ , 0x224d173fU, 0x31ef8f48U, 0x050827d1U, 0x16aabfa6U, 0x6cc776e3U, 0x7f65ee94U, 0x4b82460dU, 0x5820de7aU + /* 128 */ , 0xfbc3faf9U, 0xe861628eU, 0xdc86ca17U, 0xcf245260U, 0xb5499b25U, 0xa6eb0352U, 0x920cabcbU, 0x81ae33bcU + /* 136 */ , 0x66d73941U, 0x7575a136U, 0x419209afU, 0x523091d8U, 0x285d589dU, 0x3bffc0eaU, 0x0f186873U, 0x1cbaf004U + /* 144 */ , 0xc4060b78U, 0xd7a4930fU, 0xe3433b96U, 0xf0e1a3e1U, 0x8a8c6aa4U, 0x992ef2d3U, 0xadc95a4aU, 0xbe6bc23dU + /* 152 */ , 0x5912c8c0U, 0x4ab050b7U, 0x7e57f82eU, 0x6df56059U, 0x1798a91cU, 0x043a316bU, 0x30dd99f2U, 0x237f0185U + /* 160 */ , 0x844819fbU, 0x97ea818cU, 0xa30d2915U, 0xb0afb162U, 0xcac27827U, 0xd960e050U, 0xed8748c9U, 0xfe25d0beU + /* 168 */ , 0x195cda43U, 0x0afe4234U, 0x3e19eaadU, 0x2dbb72daU, 0x57d6bb9fU, 0x447423e8U, 0x70938b71U, 0x63311306U + /* 176 */ , 0xbb8de87aU, 0xa82f700dU, 0x9cc8d894U, 0x8f6a40e3U, 0xf50789a6U, 0xe6a511d1U, 0xd242b948U, 0xc1e0213fU + /* 184 */ , 0x26992bc2U, 0x353bb3b5U, 0x01dc1b2cU, 0x127e835bU, 0x68134a1eU, 0x7bb1d269U, 0x4f567af0U, 0x5cf4e287U + /* 192 */ , 0x04d43cfdU, 0x1776a48aU, 0x23910c13U, 0x30339464U, 0x4a5e5d21U, 0x59fcc556U, 0x6d1b6dcfU, 0x7eb9f5b8U + /* 200 */ , 0x99c0ff45U, 0x8a626732U, 0xbe85cfabU, 0xad2757dcU, 0xd74a9e99U, 0xc4e806eeU, 0xf00fae77U, 0xe3ad3600U + /* 208 */ , 0x3b11cd7cU, 0x28b3550bU, 0x1c54fd92U, 0x0ff665e5U, 0x759baca0U, 0x663934d7U, 0x52de9c4eU, 0x417c0439U + /* 216 */ , 0xa6050ec4U, 0xb5a796b3U, 0x81403e2aU, 0x92e2a65dU, 0xe88f6f18U, 0xfb2df76fU, 0xcfca5ff6U, 0xdc68c781U + /* 224 */ , 0x7b5fdfffU, 0x68fd4788U, 0x5c1aef11U, 0x4fb87766U, 0x35d5be23U, 0x26772654U, 0x12908ecdU, 0x013216baU + /* 232 */ , 0xe64b1c47U, 0xf5e98430U, 0xc10e2ca9U, 0xd2acb4deU, 0xa8c17d9bU, 0xbb63e5ecU, 0x8f844d75U, 0x9c26d502U + /* 240 */ , 0x449a2e7eU, 0x5738b609U, 0x63df1e90U, 0x707d86e7U, 0x0a104fa2U, 0x19b2d7d5U, 0x2d557f4cU, 0x3ef7e73bU + /* 248 */ , 0xd98eedc6U, 0xca2c75b1U, 0xfecbdd28U, 0xed69455fU, 0x97048c1aU, 0x84a6146dU, 0xb041bcf4U, 0xa3e32483U + } + , + /* CRC32C table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xa541927eU, 0x4f6f520dU, 0xea2ec073U, 0x9edea41aU, 0x3b9f3664U, 0xd1b1f617U, 0x74f06469U + /* 8 */ , 0x38513ec5U, 0x9d10acbbU, 0x773e6cc8U, 0xd27ffeb6U, 0xa68f9adfU, 0x03ce08a1U, 0xe9e0c8d2U, 0x4ca15aacU + /* 16 */ , 0x70a27d8aU, 0xd5e3eff4U, 0x3fcd2f87U, 0x9a8cbdf9U, 0xee7cd990U, 0x4b3d4beeU, 0xa1138b9dU, 0x045219e3U + /* 24 */ , 0x48f3434fU, 0xedb2d131U, 0x079c1142U, 0xa2dd833cU, 0xd62de755U, 0x736c752bU, 0x9942b558U, 0x3c032726U + /* 32 */ , 0xe144fb14U, 0x4405696aU, 0xae2ba919U, 0x0b6a3b67U, 0x7f9a5f0eU, 0xdadbcd70U, 0x30f50d03U, 0x95b49f7dU + /* 40 */ , 0xd915c5d1U, 0x7c5457afU, 0x967a97dcU, 0x333b05a2U, 0x47cb61cbU, 0xe28af3b5U, 0x08a433c6U, 0xade5a1b8U + /* 48 */ , 0x91e6869eU, 0x34a714e0U, 0xde89d493U, 0x7bc846edU, 0x0f382284U, 0xaa79b0faU, 0x40577089U, 0xe516e2f7U + /* 56 */ , 0xa9b7b85bU, 0x0cf62a25U, 0xe6d8ea56U, 0x43997828U, 0x37691c41U, 0x92288e3fU, 0x78064e4cU, 0xdd47dc32U + /* 64 */ , 0xc76580d9U, 0x622412a7U, 0x880ad2d4U, 0x2d4b40aaU, 0x59bb24c3U, 0xfcfab6bdU, 0x16d476ceU, 0xb395e4b0U + /* 72 */ , 0xff34be1cU, 0x5a752c62U, 0xb05bec11U, 0x151a7e6fU, 0x61ea1a06U, 0xc4ab8878U, 0x2e85480bU, 0x8bc4da75U + /* 80 */ , 0xb7c7fd53U, 0x12866f2dU, 0xf8a8af5eU, 0x5de93d20U, 0x29195949U, 0x8c58cb37U, 0x66760b44U, 0xc337993aU + /* 88 */ , 0x8f96c396U, 0x2ad751e8U, 0xc0f9919bU, 0x65b803e5U, 0x1148678cU, 0xb409f5f2U, 0x5e273581U, 0xfb66a7ffU + /* 96 */ , 0x26217bcdU, 0x8360e9b3U, 0x694e29c0U, 0xcc0fbbbeU, 0xb8ffdfd7U, 0x1dbe4da9U, 0xf7908ddaU, 0x52d11fa4U + /* 104 */ , 0x1e704508U, 0xbb31d776U, 0x511f1705U, 0xf45e857bU, 0x80aee112U, 0x25ef736cU, 0xcfc1b31fU, 0x6a802161U + /* 112 */ , 0x56830647U, 0xf3c29439U, 0x19ec544aU, 0xbcadc634U, 0xc85da25dU, 0x6d1c3023U, 0x8732f050U, 0x2273622eU + /* 120 */ , 0x6ed23882U, 0xcb93aafcU, 0x21bd6a8fU, 0x84fcf8f1U, 0xf00c9c98U, 0x554d0ee6U, 0xbf63ce95U, 0x1a225cebU + /* 128 */ , 0x8b277743U, 0x2e66e53dU, 0xc448254eU, 0x6109b730U, 0x15f9d359U, 0xb0b84127U, 0x5a968154U, 0xffd7132aU + /* 136 */ , 0xb3764986U, 0x1637dbf8U, 0xfc191b8bU, 0x595889f5U, 0x2da8ed9cU, 0x88e97fe2U, 0x62c7bf91U, 0xc7862defU + /* 144 */ , 0xfb850ac9U, 0x5ec498b7U, 0xb4ea58c4U, 0x11abcabaU, 0x655baed3U, 0xc01a3cadU, 0x2a34fcdeU, 0x8f756ea0U + /* 152 */ , 0xc3d4340cU, 0x6695a672U, 0x8cbb6601U, 0x29faf47fU, 0x5d0a9016U, 0xf84b0268U, 0x1265c21bU, 0xb7245065U + /* 160 */ , 0x6a638c57U, 0xcf221e29U, 0x250cde5aU, 0x804d4c24U, 0xf4bd284dU, 0x51fcba33U, 0xbbd27a40U, 0x1e93e83eU + /* 168 */ , 0x5232b292U, 0xf77320ecU, 0x1d5de09fU, 0xb81c72e1U, 0xccec1688U, 0x69ad84f6U, 0x83834485U, 0x26c2d6fbU + /* 176 */ , 0x1ac1f1ddU, 0xbf8063a3U, 0x55aea3d0U, 0xf0ef31aeU, 0x841f55c7U, 0x215ec7b9U, 0xcb7007caU, 0x6e3195b4U + /* 184 */ , 0x2290cf18U, 0x87d15d66U, 0x6dff9d15U, 0xc8be0f6bU, 0xbc4e6b02U, 0x190ff97cU, 0xf321390fU, 0x5660ab71U + /* 192 */ , 0x4c42f79aU, 0xe90365e4U, 0x032da597U, 0xa66c37e9U, 0xd29c5380U, 0x77ddc1feU, 0x9df3018dU, 0x38b293f3U + /* 200 */ , 0x7413c95fU, 0xd1525b21U, 0x3b7c9b52U, 0x9e3d092cU, 0xeacd6d45U, 0x4f8cff3bU, 0xa5a23f48U, 0x00e3ad36U + /* 208 */ , 0x3ce08a10U, 0x99a1186eU, 0x738fd81dU, 0xd6ce4a63U, 0xa23e2e0aU, 0x077fbc74U, 0xed517c07U, 0x4810ee79U + /* 216 */ , 0x04b1b4d5U, 0xa1f026abU, 0x4bdee6d8U, 0xee9f74a6U, 0x9a6f10cfU, 0x3f2e82b1U, 0xd50042c2U, 0x7041d0bcU + /* 224 */ , 0xad060c8eU, 0x08479ef0U, 0xe2695e83U, 0x4728ccfdU, 0x33d8a894U, 0x96993aeaU, 0x7cb7fa99U, 0xd9f668e7U + /* 232 */ , 0x9557324bU, 0x3016a035U, 0xda386046U, 0x7f79f238U, 0x0b899651U, 0xaec8042fU, 0x44e6c45cU, 0xe1a75622U + /* 240 */ , 0xdda47104U, 0x78e5e37aU, 0x92cb2309U, 0x378ab177U, 0x437ad51eU, 0xe63b4760U, 0x0c158713U, 0xa954156dU + /* 248 */ , 0xe5f54fc1U, 0x40b4ddbfU, 0xaa9a1dccU, 0x0fdb8fb2U, 0x7b2bebdbU, 0xde6a79a5U, 0x3444b9d6U, 0x91052ba8U + } + , + /* CRC32C table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xdd45aab8U, 0xbf672381U, 0x62228939U, 0x7b2231f3U, 0xa6679b4bU, 0xc4451272U, 0x1900b8caU + /* 8 */ , 0xf64463e6U, 0x2b01c95eU, 0x49234067U, 0x9466eadfU, 0x8d665215U, 0x5023f8adU, 0x32017194U, 0xef44db2cU + /* 16 */ , 0xe964b13dU, 0x34211b85U, 0x560392bcU, 0x8b463804U, 0x924680ceU, 0x4f032a76U, 0x2d21a34fU, 0xf06409f7U + /* 24 */ , 0x1f20d2dbU, 0xc2657863U, 0xa047f15aU, 0x7d025be2U, 0x6402e328U, 0xb9474990U, 0xdb65c0a9U, 0x06206a11U + /* 32 */ , 0xd725148bU, 0x0a60be33U, 0x6842370aU, 0xb5079db2U, 0xac072578U, 0x71428fc0U, 0x136006f9U, 0xce25ac41U + /* 40 */ , 0x2161776dU, 0xfc24ddd5U, 0x9e0654ecU, 0x4343fe54U, 0x5a43469eU, 0x8706ec26U, 0xe524651fU, 0x3861cfa7U + /* 48 */ , 0x3e41a5b6U, 0xe3040f0eU, 0x81268637U, 0x5c632c8fU, 0x45639445U, 0x98263efdU, 0xfa04b7c4U, 0x27411d7cU + /* 56 */ , 0xc805c650U, 0x15406ce8U, 0x7762e5d1U, 0xaa274f69U, 0xb327f7a3U, 0x6e625d1bU, 0x0c40d422U, 0xd1057e9aU + /* 64 */ , 0xaba65fe7U, 0x76e3f55fU, 0x14c17c66U, 0xc984d6deU, 0xd0846e14U, 0x0dc1c4acU, 0x6fe34d95U, 0xb2a6e72dU + /* 72 */ , 0x5de23c01U, 0x80a796b9U, 0xe2851f80U, 0x3fc0b538U, 0x26c00df2U, 0xfb85a74aU, 0x99a72e73U, 0x44e284cbU + /* 80 */ , 0x42c2eedaU, 0x9f874462U, 0xfda5cd5bU, 0x20e067e3U, 0x39e0df29U, 0xe4a57591U, 0x8687fca8U, 0x5bc25610U + /* 88 */ , 0xb4868d3cU, 0x69c32784U, 0x0be1aebdU, 0xd6a40405U, 0xcfa4bccfU, 0x12e11677U, 0x70c39f4eU, 0xad8635f6U + /* 96 */ , 0x7c834b6cU, 0xa1c6e1d4U, 0xc3e468edU, 0x1ea1c255U, 0x07a17a9fU, 0xdae4d027U, 0xb8c6591eU, 0x6583f3a6U + /* 104 */ , 0x8ac7288aU, 0x57828232U, 0x35a00b0bU, 0xe8e5a1b3U, 0xf1e51979U, 0x2ca0b3c1U, 0x4e823af8U, 0x93c79040U + /* 112 */ , 0x95e7fa51U, 0x48a250e9U, 0x2a80d9d0U, 0xf7c57368U, 0xeec5cba2U, 0x3380611aU, 0x51a2e823U, 0x8ce7429bU + /* 120 */ , 0x63a399b7U, 0xbee6330fU, 0xdcc4ba36U, 0x0181108eU, 0x1881a844U, 0xc5c402fcU, 0xa7e68bc5U, 0x7aa3217dU + /* 128 */ , 0x52a0c93fU, 0x8fe56387U, 0xedc7eabeU, 0x30824006U, 0x2982f8ccU, 0xf4c75274U, 0x96e5db4dU, 0x4ba071f5U + /* 136 */ , 0xa4e4aad9U, 0x79a10061U, 0x1b838958U, 0xc6c623e0U, 0xdfc69b2aU, 0x02833192U, 0x60a1b8abU, 0xbde41213U + /* 144 */ , 0xbbc47802U, 0x6681d2baU, 0x04a35b83U, 0xd9e6f13bU, 0xc0e649f1U, 0x1da3e349U, 0x7f816a70U, 0xa2c4c0c8U + /* 152 */ , 0x4d801be4U, 0x90c5b15cU, 0xf2e73865U, 0x2fa292ddU, 0x36a22a17U, 0xebe780afU, 0x89c50996U, 0x5480a32eU + /* 160 */ , 0x8585ddb4U, 0x58c0770cU, 0x3ae2fe35U, 0xe7a7548dU, 0xfea7ec47U, 0x23e246ffU, 0x41c0cfc6U, 0x9c85657eU + /* 168 */ , 0x73c1be52U, 0xae8414eaU, 0xcca69dd3U, 0x11e3376bU, 0x08e38fa1U, 0xd5a62519U, 0xb784ac20U, 0x6ac10698U + /* 176 */ , 0x6ce16c89U, 0xb1a4c631U, 0xd3864f08U, 0x0ec3e5b0U, 0x17c35d7aU, 0xca86f7c2U, 0xa8a47efbU, 0x75e1d443U + /* 184 */ , 0x9aa50f6fU, 0x47e0a5d7U, 0x25c22ceeU, 0xf8878656U, 0xe1873e9cU, 0x3cc29424U, 0x5ee01d1dU, 0x83a5b7a5U + /* 192 */ , 0xf90696d8U, 0x24433c60U, 0x4661b559U, 0x9b241fe1U, 0x8224a72bU, 0x5f610d93U, 0x3d4384aaU, 0xe0062e12U + /* 200 */ , 0x0f42f53eU, 0xd2075f86U, 0xb025d6bfU, 0x6d607c07U, 0x7460c4cdU, 0xa9256e75U, 0xcb07e74cU, 0x16424df4U + /* 208 */ , 0x106227e5U, 0xcd278d5dU, 0xaf050464U, 0x7240aedcU, 0x6b401616U, 0xb605bcaeU, 0xd4273597U, 0x09629f2fU + /* 216 */ , 0xe6264403U, 0x3b63eebbU, 0x59416782U, 0x8404cd3aU, 0x9d0475f0U, 0x4041df48U, 0x22635671U, 0xff26fcc9U + /* 224 */ , 0x2e238253U, 0xf36628ebU, 0x9144a1d2U, 0x4c010b6aU, 0x5501b3a0U, 0x88441918U, 0xea669021U, 0x37233a99U + /* 232 */ , 0xd867e1b5U, 0x05224b0dU, 0x6700c234U, 0xba45688cU, 0xa345d046U, 0x7e007afeU, 0x1c22f3c7U, 0xc167597fU + /* 240 */ , 0xc747336eU, 0x1a0299d6U, 0x782010efU, 0xa565ba57U, 0xbc65029dU, 0x6120a825U, 0x0302211cU, 0xde478ba4U + /* 248 */ , 0x31035088U, 0xec46fa30U, 0x8e647309U, 0x5321d9b1U, 0x4a21617bU, 0x9764cbc3U, 0xf54642faU, 0x2803e842U + } + , + /* CRC32C table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x03836bf2U, 0xf7703be1U, 0xf4f35013U, 0x1f979ac7U, 0x1c14f135U, 0xe8e7a126U, 0xeb64cad4U + /* 8 */ , 0xcf58d98aU, 0xccdbb278U, 0x3828e26bU, 0x3bab8999U, 0xd0cf434dU, 0xd34c28bfU, 0x27bf78acU, 0x243c135eU + /* 16 */ , 0x6fc75e10U, 0x6c4435e2U, 0x98b765f1U, 0x9b340e03U, 0x7050c4d7U, 0x73d3af25U, 0x8720ff36U, 0x84a394c4U + /* 24 */ , 0xa09f879aU, 0xa31cec68U, 0x57efbc7bU, 0x546cd789U, 0xbf081d5dU, 0xbc8b76afU, 0x487826bcU, 0x4bfb4d4eU + /* 32 */ , 0xde8ebd20U, 0xdd0dd6d2U, 0x29fe86c1U, 0x2a7ded33U, 0xc11927e7U, 0xc29a4c15U, 0x36691c06U, 0x35ea77f4U + /* 40 */ , 0x11d664aaU, 0x12550f58U, 0xe6a65f4bU, 0xe52534b9U, 0x0e41fe6dU, 0x0dc2959fU, 0xf931c58cU, 0xfab2ae7eU + /* 48 */ , 0xb149e330U, 0xb2ca88c2U, 0x4639d8d1U, 0x45bab323U, 0xaede79f7U, 0xad5d1205U, 0x59ae4216U, 0x5a2d29e4U + /* 56 */ , 0x7e113abaU, 0x7d925148U, 0x8961015bU, 0x8ae26aa9U, 0x6186a07dU, 0x6205cb8fU, 0x96f69b9cU, 0x9575f06eU + /* 64 */ , 0xbc1d7b41U, 0xbf9e10b3U, 0x4b6d40a0U, 0x48ee2b52U, 0xa38ae186U, 0xa0098a74U, 0x54fada67U, 0x5779b195U + /* 72 */ , 0x7345a2cbU, 0x70c6c939U, 0x8435992aU, 0x87b6f2d8U, 0x6cd2380cU, 0x6f5153feU, 0x9ba203edU, 0x9821681fU + /* 80 */ , 0xd3da2551U, 0xd0594ea3U, 0x24aa1eb0U, 0x27297542U, 0xcc4dbf96U, 0xcfced464U, 0x3b3d8477U, 0x38beef85U + /* 88 */ , 0x1c82fcdbU, 0x1f019729U, 0xebf2c73aU, 0xe871acc8U, 0x0315661cU, 0x00960deeU, 0xf4655dfdU, 0xf7e6360fU + /* 96 */ , 0x6293c661U, 0x6110ad93U, 0x95e3fd80U, 0x96609672U, 0x7d045ca6U, 0x7e873754U, 0x8a746747U, 0x89f70cb5U + /* 104 */ , 0xadcb1febU, 0xae487419U, 0x5abb240aU, 0x59384ff8U, 0xb25c852cU, 0xb1dfeedeU, 0x452cbecdU, 0x46afd53fU + /* 112 */ , 0x0d549871U, 0x0ed7f383U, 0xfa24a390U, 0xf9a7c862U, 0x12c302b6U, 0x11406944U, 0xe5b33957U, 0xe63052a5U + /* 120 */ , 0xc20c41fbU, 0xc18f2a09U, 0x357c7a1aU, 0x36ff11e8U, 0xdd9bdb3cU, 0xde18b0ceU, 0x2aebe0ddU, 0x29688b2fU + /* 128 */ , 0x783bf682U, 0x7bb89d70U, 0x8f4bcd63U, 0x8cc8a691U, 0x67ac6c45U, 0x642f07b7U, 0x90dc57a4U, 0x935f3c56U + /* 136 */ , 0xb7632f08U, 0xb4e044faU, 0x401314e9U, 0x43907f1bU, 0xa8f4b5cfU, 0xab77de3dU, 0x5f848e2eU, 0x5c07e5dcU + /* 144 */ , 0x17fca892U, 0x147fc360U, 0xe08c9373U, 0xe30ff881U, 0x086b3255U, 0x0be859a7U, 0xff1b09b4U, 0xfc986246U + /* 152 */ , 0xd8a47118U, 0xdb271aeaU, 0x2fd44af9U, 0x2c57210bU, 0xc733ebdfU, 0xc4b0802dU, 0x3043d03eU, 0x33c0bbccU + /* 160 */ , 0xa6b54ba2U, 0xa5362050U, 0x51c57043U, 0x52461bb1U, 0xb922d165U, 0xbaa1ba97U, 0x4e52ea84U, 0x4dd18176U + /* 168 */ , 0x69ed9228U, 0x6a6ef9daU, 0x9e9da9c9U, 0x9d1ec23bU, 0x767a08efU, 0x75f9631dU, 0x810a330eU, 0x828958fcU + /* 176 */ , 0xc97215b2U, 0xcaf17e40U, 0x3e022e53U, 0x3d8145a1U, 0xd6e58f75U, 0xd566e487U, 0x2195b494U, 0x2216df66U + /* 184 */ , 0x062acc38U, 0x05a9a7caU, 0xf15af7d9U, 0xf2d99c2bU, 0x19bd56ffU, 0x1a3e3d0dU, 0xeecd6d1eU, 0xed4e06ecU + /* 192 */ , 0xc4268dc3U, 0xc7a5e631U, 0x3356b622U, 0x30d5ddd0U, 0xdbb11704U, 0xd8327cf6U, 0x2cc12ce5U, 0x2f424717U + /* 200 */ , 0x0b7e5449U, 0x08fd3fbbU, 0xfc0e6fa8U, 0xff8d045aU, 0x14e9ce8eU, 0x176aa57cU, 0xe399f56fU, 0xe01a9e9dU + /* 208 */ , 0xabe1d3d3U, 0xa862b821U, 0x5c91e832U, 0x5f1283c0U, 0xb4764914U, 0xb7f522e6U, 0x430672f5U, 0x40851907U + /* 216 */ , 0x64b90a59U, 0x673a61abU, 0x93c931b8U, 0x904a5a4aU, 0x7b2e909eU, 0x78adfb6cU, 0x8c5eab7fU, 0x8fddc08dU + /* 224 */ , 0x1aa830e3U, 0x192b5b11U, 0xedd80b02U, 0xee5b60f0U, 0x053faa24U, 0x06bcc1d6U, 0xf24f91c5U, 0xf1ccfa37U + /* 232 */ , 0xd5f0e969U, 0xd673829bU, 0x2280d288U, 0x2103b97aU, 0xca6773aeU, 0xc9e4185cU, 0x3d17484fU, 0x3e9423bdU + /* 240 */ , 0x756f6ef3U, 0x76ec0501U, 0x821f5512U, 0x819c3ee0U, 0x6af8f434U, 0x697b9fc6U, 0x9d88cfd5U, 0x9e0ba427U + /* 248 */ , 0xba37b779U, 0xb9b4dc8bU, 0x4d478c98U, 0x4ec4e76aU, 0xa5a02dbeU, 0xa623464cU, 0x52d0165fU, 0x51537dadU + } + , + /* CRC32C table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7798a213U, 0xee304527U, 0x99a8e734U, 0xdc618a4eU, 0xabf9285dU, 0x3251cf69U, 0x45c96d7aU + /* 8 */ , 0xb8c3149dU, 0xcf5bb68eU, 0x56f351baU, 0x216bf3a9U, 0x64a29ed3U, 0x133a3cc0U, 0x8a92dbf4U, 0xfd0a79e7U + /* 16 */ , 0x81f1c53fU, 0xf669672cU, 0x6fc18018U, 0x1859220bU, 0x5d904f71U, 0x2a08ed62U, 0xb3a00a56U, 0xc438a845U + /* 24 */ , 0x3932d1a2U, 0x4eaa73b1U, 0xd7029485U, 0xa09a3696U, 0xe5535becU, 0x92cbf9ffU, 0x0b631ecbU, 0x7cfbbcd8U + /* 32 */ , 0x02e38b7fU, 0x757b296cU, 0xecd3ce58U, 0x9b4b6c4bU, 0xde820131U, 0xa91aa322U, 0x30b24416U, 0x472ae605U + /* 40 */ , 0xba209fe2U, 0xcdb83df1U, 0x5410dac5U, 0x238878d6U, 0x664115acU, 0x11d9b7bfU, 0x8871508bU, 0xffe9f298U + /* 48 */ , 0x83124e40U, 0xf48aec53U, 0x6d220b67U, 0x1abaa974U, 0x5f73c40eU, 0x28eb661dU, 0xb1438129U, 0xc6db233aU + /* 56 */ , 0x3bd15addU, 0x4c49f8ceU, 0xd5e11ffaU, 0xa279bde9U, 0xe7b0d093U, 0x90287280U, 0x098095b4U, 0x7e1837a7U + /* 64 */ , 0x04c617ffU, 0x735eb5ecU, 0xeaf652d8U, 0x9d6ef0cbU, 0xd8a79db1U, 0xaf3f3fa2U, 0x3697d896U, 0x410f7a85U + /* 72 */ , 0xbc050362U, 0xcb9da171U, 0x52354645U, 0x25ade456U, 0x6064892cU, 0x17fc2b3fU, 0x8e54cc0bU, 0xf9cc6e18U + /* 80 */ , 0x8537d2c0U, 0xf2af70d3U, 0x6b0797e7U, 0x1c9f35f4U, 0x5956588eU, 0x2ecefa9dU, 0xb7661da9U, 0xc0febfbaU + /* 88 */ , 0x3df4c65dU, 0x4a6c644eU, 0xd3c4837aU, 0xa45c2169U, 0xe1954c13U, 0x960dee00U, 0x0fa50934U, 0x783dab27U + /* 96 */ , 0x06259c80U, 0x71bd3e93U, 0xe815d9a7U, 0x9f8d7bb4U, 0xda4416ceU, 0xaddcb4ddU, 0x347453e9U, 0x43ecf1faU + /* 104 */ , 0xbee6881dU, 0xc97e2a0eU, 0x50d6cd3aU, 0x274e6f29U, 0x62870253U, 0x151fa040U, 0x8cb74774U, 0xfb2fe567U + /* 112 */ , 0x87d459bfU, 0xf04cfbacU, 0x69e41c98U, 0x1e7cbe8bU, 0x5bb5d3f1U, 0x2c2d71e2U, 0xb58596d6U, 0xc21d34c5U + /* 120 */ , 0x3f174d22U, 0x488fef31U, 0xd1270805U, 0xa6bfaa16U, 0xe376c76cU, 0x94ee657fU, 0x0d46824bU, 0x7ade2058U + /* 128 */ , 0xf9fac3fbU, 0x8e6261e8U, 0x17ca86dcU, 0x605224cfU, 0x259b49b5U, 0x5203eba6U, 0xcbab0c92U, 0xbc33ae81U + /* 136 */ , 0x4139d766U, 0x36a17575U, 0xaf099241U, 0xd8913052U, 0x9d585d28U, 0xeac0ff3bU, 0x7368180fU, 0x04f0ba1cU + /* 144 */ , 0x780b06c4U, 0x0f93a4d7U, 0x963b43e3U, 0xe1a3e1f0U, 0xa46a8c8aU, 0xd3f22e99U, 0x4a5ac9adU, 0x3dc26bbeU + /* 152 */ , 0xc0c81259U, 0xb750b04aU, 0x2ef8577eU, 0x5960f56dU, 0x1ca99817U, 0x6b313a04U, 0xf299dd30U, 0x85017f23U + /* 160 */ , 0xfb194884U, 0x8c81ea97U, 0x15290da3U, 0x62b1afb0U, 0x2778c2caU, 0x50e060d9U, 0xc94887edU, 0xbed025feU + /* 168 */ , 0x43da5c19U, 0x3442fe0aU, 0xadea193eU, 0xda72bb2dU, 0x9fbbd657U, 0xe8237444U, 0x718b9370U, 0x06133163U + /* 176 */ , 0x7ae88dbbU, 0x0d702fa8U, 0x94d8c89cU, 0xe3406a8fU, 0xa68907f5U, 0xd111a5e6U, 0x48b942d2U, 0x3f21e0c1U + /* 184 */ , 0xc22b9926U, 0xb5b33b35U, 0x2c1bdc01U, 0x5b837e12U, 0x1e4a1368U, 0x69d2b17bU, 0xf07a564fU, 0x87e2f45cU + /* 192 */ , 0xfd3cd404U, 0x8aa47617U, 0x130c9123U, 0x64943330U, 0x215d5e4aU, 0x56c5fc59U, 0xcf6d1b6dU, 0xb8f5b97eU + /* 200 */ , 0x45ffc099U, 0x3267628aU, 0xabcf85beU, 0xdc5727adU, 0x999e4ad7U, 0xee06e8c4U, 0x77ae0ff0U, 0x0036ade3U + /* 208 */ , 0x7ccd113bU, 0x0b55b328U, 0x92fd541cU, 0xe565f60fU, 0xa0ac9b75U, 0xd7343966U, 0x4e9cde52U, 0x39047c41U + /* 216 */ , 0xc40e05a6U, 0xb396a7b5U, 0x2a3e4081U, 0x5da6e292U, 0x186f8fe8U, 0x6ff72dfbU, 0xf65fcacfU, 0x81c768dcU + /* 224 */ , 0xffdf5f7bU, 0x8847fd68U, 0x11ef1a5cU, 0x6677b84fU, 0x23bed535U, 0x54267726U, 0xcd8e9012U, 0xba163201U + /* 232 */ , 0x471c4be6U, 0x3084e9f5U, 0xa92c0ec1U, 0xdeb4acd2U, 0x9b7dc1a8U, 0xece563bbU, 0x754d848fU, 0x02d5269cU + /* 240 */ , 0x7e2e9a44U, 0x09b63857U, 0x901edf63U, 0xe7867d70U, 0xa24f100aU, 0xd5d7b219U, 0x4c7f552dU, 0x3be7f73eU + /* 248 */ , 0xc6ed8ed9U, 0xb1752ccaU, 0x28ddcbfeU, 0x5f4569edU, 0x1a8c0497U, 0x6d14a684U, 0xf4bc41b0U, 0x8324e3a3U + } + , + /* CRC32C table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7e9241a5U, 0x0d526f4fU, 0x73c02eeaU, 0x1aa4de9eU, 0x64369f3bU, 0x17f6b1d1U, 0x6964f074U + /* 8 */ , 0xc53e5138U, 0xbbac109dU, 0xc86c3e77U, 0xb6fe7fd2U, 0xdf9a8fa6U, 0xa108ce03U, 0xd2c8e0e9U, 0xac5aa14cU + /* 16 */ , 0x8a7da270U, 0xf4efe3d5U, 0x872fcd3fU, 0xf9bd8c9aU, 0x90d97ceeU, 0xee4b3d4bU, 0x9d8b13a1U, 0xe3195204U + /* 24 */ , 0x4f43f348U, 0x31d1b2edU, 0x42119c07U, 0x3c83dda2U, 0x55e72dd6U, 0x2b756c73U, 0x58b54299U, 0x2627033cU + /* 32 */ , 0x14fb44e1U, 0x6a690544U, 0x19a92baeU, 0x673b6a0bU, 0x0e5f9a7fU, 0x70cddbdaU, 0x030df530U, 0x7d9fb495U + /* 40 */ , 0xd1c515d9U, 0xaf57547cU, 0xdc977a96U, 0xa2053b33U, 0xcb61cb47U, 0xb5f38ae2U, 0xc633a408U, 0xb8a1e5adU + /* 48 */ , 0x9e86e691U, 0xe014a734U, 0x93d489deU, 0xed46c87bU, 0x8422380fU, 0xfab079aaU, 0x89705740U, 0xf7e216e5U + /* 56 */ , 0x5bb8b7a9U, 0x252af60cU, 0x56ead8e6U, 0x28789943U, 0x411c6937U, 0x3f8e2892U, 0x4c4e0678U, 0x32dc47ddU + /* 64 */ , 0xd98065c7U, 0xa7122462U, 0xd4d20a88U, 0xaa404b2dU, 0xc324bb59U, 0xbdb6fafcU, 0xce76d416U, 0xb0e495b3U + /* 72 */ , 0x1cbe34ffU, 0x622c755aU, 0x11ec5bb0U, 0x6f7e1a15U, 0x061aea61U, 0x7888abc4U, 0x0b48852eU, 0x75dac48bU + /* 80 */ , 0x53fdc7b7U, 0x2d6f8612U, 0x5eafa8f8U, 0x203de95dU, 0x49591929U, 0x37cb588cU, 0x440b7666U, 0x3a9937c3U + /* 88 */ , 0x96c3968fU, 0xe851d72aU, 0x9b91f9c0U, 0xe503b865U, 0x8c674811U, 0xf2f509b4U, 0x8135275eU, 0xffa766fbU + /* 96 */ , 0xcd7b2126U, 0xb3e96083U, 0xc0294e69U, 0xbebb0fccU, 0xd7dfffb8U, 0xa94dbe1dU, 0xda8d90f7U, 0xa41fd152U + /* 104 */ , 0x0845701eU, 0x76d731bbU, 0x05171f51U, 0x7b855ef4U, 0x12e1ae80U, 0x6c73ef25U, 0x1fb3c1cfU, 0x6121806aU + /* 112 */ , 0x47068356U, 0x3994c2f3U, 0x4a54ec19U, 0x34c6adbcU, 0x5da25dc8U, 0x23301c6dU, 0x50f03287U, 0x2e627322U + /* 120 */ , 0x8238d26eU, 0xfcaa93cbU, 0x8f6abd21U, 0xf1f8fc84U, 0x989c0cf0U, 0xe60e4d55U, 0x95ce63bfU, 0xeb5c221aU + /* 128 */ , 0x4377278bU, 0x3de5662eU, 0x4e2548c4U, 0x30b70961U, 0x59d3f915U, 0x2741b8b0U, 0x5481965aU, 0x2a13d7ffU + /* 136 */ , 0x864976b3U, 0xf8db3716U, 0x8b1b19fcU, 0xf5895859U, 0x9ceda82dU, 0xe27fe988U, 0x91bfc762U, 0xef2d86c7U + /* 144 */ , 0xc90a85fbU, 0xb798c45eU, 0xc458eab4U, 0xbacaab11U, 0xd3ae5b65U, 0xad3c1ac0U, 0xdefc342aU, 0xa06e758fU + /* 152 */ , 0x0c34d4c3U, 0x72a69566U, 0x0166bb8cU, 0x7ff4fa29U, 0x16900a5dU, 0x68024bf8U, 0x1bc26512U, 0x655024b7U + /* 160 */ , 0x578c636aU, 0x291e22cfU, 0x5ade0c25U, 0x244c4d80U, 0x4d28bdf4U, 0x33bafc51U, 0x407ad2bbU, 0x3ee8931eU + /* 168 */ , 0x92b23252U, 0xec2073f7U, 0x9fe05d1dU, 0xe1721cb8U, 0x8816ecccU, 0xf684ad69U, 0x85448383U, 0xfbd6c226U + /* 176 */ , 0xddf1c11aU, 0xa36380bfU, 0xd0a3ae55U, 0xae31eff0U, 0xc7551f84U, 0xb9c75e21U, 0xca0770cbU, 0xb495316eU + /* 184 */ , 0x18cf9022U, 0x665dd187U, 0x159dff6dU, 0x6b0fbec8U, 0x026b4ebcU, 0x7cf90f19U, 0x0f3921f3U, 0x71ab6056U + /* 192 */ , 0x9af7424cU, 0xe46503e9U, 0x97a52d03U, 0xe9376ca6U, 0x80539cd2U, 0xfec1dd77U, 0x8d01f39dU, 0xf393b238U + /* 200 */ , 0x5fc91374U, 0x215b52d1U, 0x529b7c3bU, 0x2c093d9eU, 0x456dcdeaU, 0x3bff8c4fU, 0x483fa2a5U, 0x36ade300U + /* 208 */ , 0x108ae03cU, 0x6e18a199U, 0x1dd88f73U, 0x634aced6U, 0x0a2e3ea2U, 0x74bc7f07U, 0x077c51edU, 0x79ee1048U + /* 216 */ , 0xd5b4b104U, 0xab26f0a1U, 0xd8e6de4bU, 0xa6749feeU, 0xcf106f9aU, 0xb1822e3fU, 0xc24200d5U, 0xbcd04170U + /* 224 */ , 0x8e0c06adU, 0xf09e4708U, 0x835e69e2U, 0xfdcc2847U, 0x94a8d833U, 0xea3a9996U, 0x99fab77cU, 0xe768f6d9U + /* 232 */ , 0x4b325795U, 0x35a01630U, 0x466038daU, 0x38f2797fU, 0x5196890bU, 0x2f04c8aeU, 0x5cc4e644U, 0x2256a7e1U + /* 240 */ , 0x0471a4ddU, 0x7ae3e578U, 0x0923cb92U, 0x77b18a37U, 0x1ed57a43U, 0x60473be6U, 0x1387150cU, 0x6d1554a9U + /* 248 */ , 0xc14ff5e5U, 0xbfddb440U, 0xcc1d9aaaU, 0xb28fdb0fU, 0xdbeb2b7bU, 0xa5796adeU, 0xd6b94434U, 0xa82b0591U + } + , + /* CRC32C table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8aa45ddU, 0x812367bfU, 0x39892262U, 0xf331227bU, 0x4b9b67a6U, 0x721245c4U, 0xcab80019U + /* 8 */ , 0xe66344f6U, 0x5ec9012bU, 0x67402349U, 0xdfea6694U, 0x1552668dU, 0xadf82350U, 0x94710132U, 0x2cdb44efU + /* 16 */ , 0x3db164e9U, 0x851b2134U, 0xbc920356U, 0x0438468bU, 0xce804692U, 0x762a034fU, 0x4fa3212dU, 0xf70964f0U + /* 24 */ , 0xdbd2201fU, 0x637865c2U, 0x5af147a0U, 0xe25b027dU, 0x28e30264U, 0x904947b9U, 0xa9c065dbU, 0x116a2006U + /* 32 */ , 0x8b1425d7U, 0x33be600aU, 0x0a374268U, 0xb29d07b5U, 0x782507acU, 0xc08f4271U, 0xf9066013U, 0x41ac25ceU + /* 40 */ , 0x6d776121U, 0xd5dd24fcU, 0xec54069eU, 0x54fe4343U, 0x9e46435aU, 0x26ec0687U, 0x1f6524e5U, 0xa7cf6138U + /* 48 */ , 0xb6a5413eU, 0x0e0f04e3U, 0x37862681U, 0x8f2c635cU, 0x45946345U, 0xfd3e2698U, 0xc4b704faU, 0x7c1d4127U + /* 56 */ , 0x50c605c8U, 0xe86c4015U, 0xd1e56277U, 0x694f27aaU, 0xa3f727b3U, 0x1b5d626eU, 0x22d4400cU, 0x9a7e05d1U + /* 64 */ , 0xe75fa6abU, 0x5ff5e376U, 0x667cc114U, 0xded684c9U, 0x146e84d0U, 0xacc4c10dU, 0x954de36fU, 0x2de7a6b2U + /* 72 */ , 0x013ce25dU, 0xb996a780U, 0x801f85e2U, 0x38b5c03fU, 0xf20dc026U, 0x4aa785fbU, 0x732ea799U, 0xcb84e244U + /* 80 */ , 0xdaeec242U, 0x6244879fU, 0x5bcda5fdU, 0xe367e020U, 0x29dfe039U, 0x9175a5e4U, 0xa8fc8786U, 0x1056c25bU + /* 88 */ , 0x3c8d86b4U, 0x8427c369U, 0xbdaee10bU, 0x0504a4d6U, 0xcfbca4cfU, 0x7716e112U, 0x4e9fc370U, 0xf63586adU + /* 96 */ , 0x6c4b837cU, 0xd4e1c6a1U, 0xed68e4c3U, 0x55c2a11eU, 0x9f7aa107U, 0x27d0e4daU, 0x1e59c6b8U, 0xa6f38365U + /* 104 */ , 0x8a28c78aU, 0x32828257U, 0x0b0ba035U, 0xb3a1e5e8U, 0x7919e5f1U, 0xc1b3a02cU, 0xf83a824eU, 0x4090c793U + /* 112 */ , 0x51fae795U, 0xe950a248U, 0xd0d9802aU, 0x6873c5f7U, 0xa2cbc5eeU, 0x1a618033U, 0x23e8a251U, 0x9b42e78cU + /* 120 */ , 0xb799a363U, 0x0f33e6beU, 0x36bac4dcU, 0x8e108101U, 0x44a88118U, 0xfc02c4c5U, 0xc58be6a7U, 0x7d21a37aU + /* 128 */ , 0x3fc9a052U, 0x8763e58fU, 0xbeeac7edU, 0x06408230U, 0xccf88229U, 0x7452c7f4U, 0x4ddbe596U, 0xf571a04bU + /* 136 */ , 0xd9aae4a4U, 0x6100a179U, 0x5889831bU, 0xe023c6c6U, 0x2a9bc6dfU, 0x92318302U, 0xabb8a160U, 0x1312e4bdU + /* 144 */ , 0x0278c4bbU, 0xbad28166U, 0x835ba304U, 0x3bf1e6d9U, 0xf149e6c0U, 0x49e3a31dU, 0x706a817fU, 0xc8c0c4a2U + /* 152 */ , 0xe41b804dU, 0x5cb1c590U, 0x6538e7f2U, 0xdd92a22fU, 0x172aa236U, 0xaf80e7ebU, 0x9609c589U, 0x2ea38054U + /* 160 */ , 0xb4dd8585U, 0x0c77c058U, 0x35fee23aU, 0x8d54a7e7U, 0x47eca7feU, 0xff46e223U, 0xc6cfc041U, 0x7e65859cU + /* 168 */ , 0x52bec173U, 0xea1484aeU, 0xd39da6ccU, 0x6b37e311U, 0xa18fe308U, 0x1925a6d5U, 0x20ac84b7U, 0x9806c16aU + /* 176 */ , 0x896ce16cU, 0x31c6a4b1U, 0x084f86d3U, 0xb0e5c30eU, 0x7a5dc317U, 0xc2f786caU, 0xfb7ea4a8U, 0x43d4e175U + /* 184 */ , 0x6f0fa59aU, 0xd7a5e047U, 0xee2cc225U, 0x568687f8U, 0x9c3e87e1U, 0x2494c23cU, 0x1d1de05eU, 0xa5b7a583U + /* 192 */ , 0xd89606f9U, 0x603c4324U, 0x59b56146U, 0xe11f249bU, 0x2ba72482U, 0x930d615fU, 0xaa84433dU, 0x122e06e0U + /* 200 */ , 0x3ef5420fU, 0x865f07d2U, 0xbfd625b0U, 0x077c606dU, 0xcdc46074U, 0x756e25a9U, 0x4ce707cbU, 0xf44d4216U + /* 208 */ , 0xe5276210U, 0x5d8d27cdU, 0x640405afU, 0xdcae4072U, 0x1616406bU, 0xaebc05b6U, 0x973527d4U, 0x2f9f6209U + /* 216 */ , 0x034426e6U, 0xbbee633bU, 0x82674159U, 0x3acd0484U, 0xf075049dU, 0x48df4140U, 0x71566322U, 0xc9fc26ffU + /* 224 */ , 0x5382232eU, 0xeb2866f3U, 0xd2a14491U, 0x6a0b014cU, 0xa0b30155U, 0x18194488U, 0x219066eaU, 0x993a2337U + /* 232 */ , 0xb5e167d8U, 0x0d4b2205U, 0x34c20067U, 0x8c6845baU, 0x46d045a3U, 0xfe7a007eU, 0xc7f3221cU, 0x7f5967c1U + /* 240 */ , 0x6e3347c7U, 0xd699021aU, 0xef102078U, 0x57ba65a5U, 0x9d0265bcU, 0x25a82061U, 0x1c210203U, 0xa48b47deU + /* 248 */ , 0x88500331U, 0x30fa46ecU, 0x0973648eU, 0xb1d92153U, 0x7b61214aU, 0xc3cb6497U, 0xfa4246f5U, 0x42e80328U + } + #endif + }; juint* StubRoutines::ppc64::_constants = StubRoutines::ppc64::generate_crc_constants(); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index ab87c204018..beefd27a4fe 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2017 SAP SE. All rights reserved. + * Copyright (c) 2015, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -643,12 +643,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - __ unimplemented("generate_continuation_for"); - return entry; -} - // This entry is returned to when a call returns to the interpreter. // When we arrive here, we expect that the callee stack frame is already popped. address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { @@ -692,6 +686,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, #endif __ sldi(size, size, Interpreter::logStackElementSize); __ add(R15_esp, R15_esp, size); + + __ check_and_handle_popframe(R11_scratch1); + __ check_and_handle_earlyret(R11_scratch1); + __ dispatch_next(state, step); return entry; } @@ -1894,7 +1892,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { __ lwz(crc, 2*wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_singleByte(crc, data, dataLen, table, tmp); + __ kernel_crc32_singleByte(crc, data, dataLen, table, tmp, true); // Restore caller sp for c2i case and return. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. @@ -1910,7 +1908,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { return NULL; } -// CRC32 Intrinsics. + /** * Method entry for static native methods: * int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len) @@ -1986,7 +1984,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // Performance measurements show the 1word and 2word variants to be almost equivalent, // with very light advantages for the 1word variant. We chose the 1word variant for // code compactness. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, true); // Restore caller sp for c2i case and return. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. @@ -2002,8 +2000,88 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI return NULL; } -// Not supported + +/** + * Method entry for intrinsic-candidate (non-native) methods: + * int java.util.zip.CRC32C.updateBytes( int crc, byte[] b, int off, int end) + * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long* buf, int off, int end) + * Unlike CRC32, CRC32C does not have any methods marked as native + * CRC32C also uses an "end" variable instead of the length variable CRC32 uses + **/ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + if (UseCRC32CIntrinsics) { + address start = __ pc(); // Remember stub start address (is rtn value). + + // We don't generate local frame and don't align stack because + // we not even call stub code (we generate the code inline) + // and there is no safepoint on this path. + + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = R15_esp; + const Register crc = R3_ARG1; // crc value + const Register data = R4_ARG2; // address of java byte array + const Register dataLen = R5_ARG3; // source data len + const Register table = R6_ARG4; // address of crc32c table + + const Register t0 = R9; // scratch registers for crc calculation + const Register t1 = R10; + const Register t2 = R11; + const Register t3 = R12; + + const Register tc0 = R2; // registers to hold pre-calculated column addresses + const Register tc1 = R7; + const Register tc2 = R8; + const Register tc3 = table; // table address is reconstructed at the end of kernel_crc32_* emitters + + const Register tmp = t0; // Only used very locally to calculate byte buffer address. + + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateDirectByteBuffer". + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ lwz( crc, 5*wordSize, argP); // current crc state + __ add( data, data, tmp); // Add byte buffer offset. + __ sub( dataLen, dataLen, tmp); // (end_index - offset) + } else { // Used for "updateBytes update". + BLOCK_COMMENT("CRC32C_updateBytes {"); + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ add( data, data, tmp); // add byte buffer offset + __ sub( dataLen, dataLen, tmp); // (end_index - offset) + __ lwz( crc, 4*wordSize, argP); // current crc state + __ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); + } + + StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table); + + // Performance measurements show the 1word and 2word variants to be almost equivalent, + // with very light advantages for the 1word variant. We chose the 1word variant for + // code compactness. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, false); + + // Restore caller sp for c2i case and return. + __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. + __ blr(); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return start; + } + return NULL; } diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index 517a304d4e3..68865489de2 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, 2016 SAP SE. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3660,11 +3660,9 @@ void TemplateTable::_new() { __ cmpdi(CCR0, Rtags, JVM_CONSTANT_Class); __ bne(CCR0, Lslow_case); - // Get instanceKlass (load from Rcpool + sizeof(ConstantPool) + Rindex*BytesPerWord). + // Get instanceKlass __ sldi(Roffset, Rindex, LogBytesPerWord); - __ addi(Rscratch, Rcpool, sizeof(ConstantPool)); - __ isync(); // Order load of instance Klass wrt. tags. - __ ldx(RinstanceKlass, Roffset, Rscratch); + __ load_resolved_klass_at_offset(Rcpool, Roffset, RinstanceKlass); // Make sure klass is fully initialized and get instance_size. __ lbz(Rscratch, in_bytes(InstanceKlass::init_state_offset()), RinstanceKlass); @@ -3722,7 +3720,7 @@ void TemplateTable::_new() { __ bge(CCR0, Lslow_case); // Increment waste limit to prevent getting stuck on this slow path. - __ addi(RtlabWasteLimitValue, RtlabWasteLimitValue, (int)ThreadLocalAllocBuffer::refill_waste_limit_increment()); + __ add_const_optimized(RtlabWasteLimitValue, RtlabWasteLimitValue, ThreadLocalAllocBuffer::refill_waste_limit_increment()); __ std(RtlabWasteLimitValue, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), R16_thread); } // else: No allocation in the shared eden. // fallthru: __ b(Lslow_case); @@ -3875,9 +3873,7 @@ void TemplateTable::checkcast() { // Extract target class from constant pool. __ bind(Lquicked); __ sldi(Roffset, Roffset, LogBytesPerWord); - __ addi(Rcpool, Rcpool, sizeof(ConstantPool)); - __ isync(); // Order load of specified Klass wrt. tags. - __ ldx(RspecifiedKlass, Rcpool, Roffset); + __ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass); // Do the checkcast. __ bind(Lresolved); @@ -3939,9 +3935,7 @@ void TemplateTable::instanceof() { // Extract target class from constant pool. __ bind(Lquicked); __ sldi(Roffset, Roffset, LogBytesPerWord); - __ addi(Rcpool, Rcpool, sizeof(ConstantPool)); - __ isync(); // Order load of specified Klass wrt. tags. - __ ldx(RspecifiedKlass, Rcpool, Roffset); + __ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass); // Do the checkcast. __ bind(Lresolved); diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index 5e8be1425fa..08e02ffbabc 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,7 +111,7 @@ void VM_Version::initialize() { // Create and print feature-string. char buf[(num_features+1) * 16]; // Max 16 chars per feature. jio_snprintf(buf, sizeof(buf), - "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (has_fsqrt() ? " fsqrt" : ""), (has_isel() ? " isel" : ""), (has_lxarxeh() ? " lxarxeh" : ""), @@ -126,7 +126,9 @@ void VM_Version::initialize() { (has_vpmsumb() ? " vpmsumb" : ""), (has_tcheck() ? " tcheck" : ""), (has_mfdscr() ? " mfdscr" : ""), - (has_vsx() ? " vsx" : "") + (has_vsx() ? " vsx" : ""), + (has_ldbrx() ? " ldbrx" : ""), + (has_stdbrx() ? " stdbrx" : "") // Make sure number of %s matches num_features! ); _features_string = os::strdup(buf); @@ -172,18 +174,27 @@ void VM_Version::initialize() { assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); - // Implementation does not use any of the vector instructions - // available with Power8. Their exploitation is still pending. + // If defined(VM_LITTLE_ENDIAN) and running on Power8 or newer hardware, + // the implementation uses the vector instructions available with Power8. + // In all other cases, the implementation uses only generally available instructions. if (!UseCRC32Intrinsics) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } } - if (UseCRC32CIntrinsics) { - if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) - warning("CRC32C intrinsics are not available on this CPU"); - FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + // Implementation does not use any of the vector instructions available with Power8. + // Their exploitation is still pending (aka "work in progress"). + if (!UseCRC32CIntrinsics) { + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + } + + // TODO: Provide implementation. + if (UseAdler32Intrinsics) { + warning("Adler32Intrinsics not available on this CPU."); + FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); } // The AES intrinsic stubs require AES instruction support. @@ -245,11 +256,6 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } - if (UseAdler32Intrinsics) { - warning("Adler32Intrinsics not available on this CPU."); - FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); - } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } @@ -659,6 +665,8 @@ void VM_Version::determine_features() { a->tcheck(0); // code[12] -> tcheck a->mfdscr(R0); // code[13] -> mfdscr a->lxvd2x(VSR0, R3_ARG1); // code[14] -> vsx + a->ldbrx(R7, R3_ARG1, R4_ARG2); // code[15] -> ldbrx + a->stdbrx(R7, R3_ARG1, R4_ARG2); // code[16] -> stdbrx a->blr(); // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it. @@ -708,6 +716,8 @@ void VM_Version::determine_features() { if (code[feature_cntr++]) features |= tcheck_m; if (code[feature_cntr++]) features |= mfdscr_m; if (code[feature_cntr++]) features |= vsx_m; + if (code[feature_cntr++]) features |= ldbrx_m; + if (code[feature_cntr++]) features |= stdbrx_m; // Print the detection code. if (PrintAssembly) { diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp index 2d1f8db990e..41fe4568510 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp @@ -47,6 +47,8 @@ protected: tcheck, mfdscr, vsx, + ldbrx, + stdbrx, num_features // last entry to count features }; enum Feature_Flag_Set { @@ -66,6 +68,8 @@ protected: tcheck_m = (1 << tcheck ), mfdscr_m = (1 << mfdscr ), vsx_m = (1 << vsx ), + ldbrx_m = (1 << ldbrx ), + stdbrx_m = (1 << stdbrx ), all_features_m = (unsigned long)-1 }; @@ -100,6 +104,8 @@ public: static bool has_tcheck() { return (_features & tcheck_m) != 0; } static bool has_mfdscr() { return (_features & mfdscr_m) != 0; } static bool has_vsx() { return (_features & vsx_m) != 0; } + static bool has_ldbrx() { return (_features & ldbrx_m) != 0; } + static bool has_stdbrx() { return (_features & stdbrx_m) != 0; } // Assembler testing static void allow_all(); diff --git a/hotspot/src/cpu/s390/vm/assembler_s390.hpp b/hotspot/src/cpu/s390/vm/assembler_s390.hpp index 0873d71b00e..8a7ae9d0756 100644 --- a/hotspot/src/cpu/s390/vm/assembler_s390.hpp +++ b/hotspot/src/cpu/s390/vm/assembler_s390.hpp @@ -28,8 +28,6 @@ #undef LUCY_DBG -#define NearLabel Label - // Immediate is an abstraction to represent the various immediate // operands which exist on z/Architecture. Neither this class nor // instances hereof have an own state. It consists of methods only. diff --git a/hotspot/src/cpu/s390/vm/bytes_s390.hpp b/hotspot/src/cpu/s390/vm/bytes_s390.hpp index 6209624d335..f01ea07a2e2 100644 --- a/hotspot/src/cpu/s390/vm/bytes_s390.hpp +++ b/hotspot/src/cpu/s390/vm/bytes_s390.hpp @@ -42,12 +42,6 @@ class Bytes: AllStatic { // // In short, it makes no sense on z/Architecture to piecemeal get or put unaligned data. - // Returns true if the byte ordering used by Java is different from - // the native byte ordering of the underlying machine. - // z/Arch is big endian, thus, a swap between native and Java ordering - // is always a no-op. - static inline bool is_Java_byte_ordering_different() { return false; } - // Only swap on little endian machines => suffix `_le'. static inline u2 swap_u2_le(u2 x) { return x; } static inline u4 swap_u4_le(u4 x) { return x; } diff --git a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp index 84fb4205099..2f75604e2b0 100644 --- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3048,9 +3048,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { assert_different_registers(val, crc, res); __ load_const_optimized(res, StubRoutines::crc_table_addr()); - __ not_(crc, noreg, false); // ~crc - __ update_byte_crc32(crc, val, res); - __ not_(res, crc, false); // ~crc + __ kernel_crc32_singleByteReg(crc, val, res, true); + __ z_lgfr(res, crc); } #undef __ diff --git a/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp index 0ec97da6230..8ebecadd85c 100644 --- a/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,20 +61,6 @@ void LIRItem::load_nonconstant(int bits) { } } -inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) { - LIR_Opr r = li.value()->operand(); - if (r->is_constant()) { - // Constants get loaded with sign extend on this platform. - ll->move(li.result(), dst); - } else { - if (!r->is_register()) { - li.load_item_force(dst); - } - LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register()); - ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert. - } -} - //-------------------------------------------------------------- // LIRGenerator //-------------------------------------------------------------- @@ -1224,10 +1210,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { LIR_Opr arg2 = cc->at(1); LIR_Opr arg3 = cc->at(2); - // CCallingConventionRequiresIntsAsLongs crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. __ leal(LIR_OprFact::address(a), arg2); - load_int_as_long(gen()->lir(), len, arg3); + len.load_item_force(arg3); // We skip int->long conversion here, because CRC32 stub expects int. __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ move(result_reg, result); @@ -1240,7 +1225,70 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } void LIRGenerator::do_update_CRC32C(Intrinsic* x) { - Unimplemented(); + assert(UseCRC32CIntrinsics, "or should not be here"); + LIR_Opr result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: { + bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C); + + LIRItem crc(x->argument_at(0), this); + LIRItem buf(x->argument_at(1), this); + LIRItem off(x->argument_at(2), this); + LIRItem end(x->argument_at(3), this); + buf.load_item(); + off.load_nonconstant(); + end.load_nonconstant(); + + // len = end - off + LIR_Opr len = end.result(); + LIR_Opr tmpA = new_register(T_INT); + LIR_Opr tmpB = new_register(T_INT); + __ move(end.result(), tmpA); + __ move(off.result(), tmpB); + __ sub(tmpA, tmpB, tmpA); + len = tmpA; + + LIR_Opr index = off.result(); + int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0; + if (off.result()->is_constant()) { + index = LIR_OprFact::illegalOpr; + offset += off.result()->as_jint(); + } + LIR_Opr base_op = buf.result(); + + if (index->is_valid()) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index, tmp); + index = tmp; + } + + LIR_Address* a = new LIR_Address(base_op, index, offset, T_BYTE); + + BasicTypeList signature(3); + signature.append(T_INT); + signature.append(T_ADDRESS); + signature.append(T_INT); + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + const LIR_Opr result_reg = result_register_for (x->type()); + + LIR_Opr arg1 = cc->at(0); + LIR_Opr arg2 = cc->at(1); + LIR_Opr arg3 = cc->at(2); + + crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32C stub doesn't care about high bits. + __ leal(LIR_OprFact::address(a), arg2); + __ move(len, cc->at(2)); // We skip int->long conversion here, because CRC32C stub expects int. + + __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args()); + __ move(result_reg, result); + break; + } + default: { + ShouldNotReachHere(); + } + } } void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { @@ -1271,4 +1319,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } - diff --git a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp index 8cec2da25ac..bdbc7031872 100644 --- a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp +++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,24 +107,15 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, address* table) { // TODO: Maybe implement +VerifyActivationFrameSize here. // verify_thread(); // Too slow. We will just verify on method entry & exit. verify_oop(Z_tos, state); -#ifdef FAST_DISPATCH - if (table == Interpreter::dispatch_table(state)) { - // Use IdispatchTables. - add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); - // Add offset to correct dispatch table. - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // Multiply by wordSize. - ld_ptr(IdispatchTables, Lbyte_code, G3_scratch); // Get entry addr. - } else -#endif - { - // Dispatch table to use. - load_absolute_address(Z_tmp_1, (address) table); // Z_tmp_1 = table; - // 0 <= Z_bytecode < 256 => Use a 32 bit shift, because it is shorter than sllg. - // Z_bytecode must have been loaded zero-extended for this approach to be correct. - z_sll(Z_bytecode, LogBytesPerWord, Z_R0); // Multiply by wordSize. - z_lg(Z_tmp_1, 0, Z_bytecode, Z_tmp_1); // Get entry addr. - } + // Dispatch table to use. + load_absolute_address(Z_tmp_1, (address) table); // Z_tmp_1 = table; + + // 0 <= Z_bytecode < 256 => Use a 32 bit shift, because it is shorter than sllg. + // Z_bytecode must have been loaded zero-extended for this approach to be correct. + z_sll(Z_bytecode, LogBytesPerWord, Z_R0); // Multiply by wordSize. + z_lg(Z_tmp_1, 0, Z_bytecode, Z_tmp_1); // Get entry addr. + z_br(Z_tmp_1); } @@ -371,7 +362,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result Register tmp = index; // reuse z_sllg(index, index, LogBytesPerHeapOop); // Offset into resolved references array. // Load pointer for resolved_references[] objArray. - z_lg(result, ConstantPool::resolved_references_offset_in_bytes(), result); + z_lg(result, ConstantPool::cache_offset_in_bytes(), result); + z_lg(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result); // JNIHandles::resolve(result) z_lg(result, 0, result); // Load resolved references array itself. #ifdef ASSERT @@ -386,6 +378,16 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result); } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass) { + // int value = *(Rcpool->int_at_addr(which)); + // int resolved_klass_index = extract_low_short_from_int(value); + z_llgh(offset, Address(cpool, offset, sizeof(ConstantPool) + 2)); // offset = resolved_klass_index (s390 is big-endian) + z_sllg(offset, offset, LogBytesPerWord); // Convert 'index' to 'offset' + z_lg(iklass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // iklass = cpool->_resolved_klasses + z_lg(iklass, Address(iklass, offset, Array::base_offset_in_bytes())); +} + void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, diff --git a/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp b/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp index 5f29a606481..bebbb4a7445 100644 --- a/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp +++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler { bool allow_relocation, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // Base routine for all dispatches. void dispatch_base(TosState state, address* table); @@ -58,6 +55,9 @@ class InterpreterMacroAssembler: public MacroAssembler { InterpreterMacroAssembler(CodeBuffer* c) : MacroAssembler(c) {} + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + void jump_to_entry(address entry, Register Rscratch); virtual void load_earlyret_value(TosState state); @@ -115,6 +115,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass); // Pop topmost element from stack. It just disappears. Useful if // consumed previously by access via stackTop(). diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp index d5776117436..7702289dcc6 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1616,6 +1616,8 @@ void MacroAssembler::branch_optimized(Assembler::branch_condition cond, Label& b if (branch_target.is_bound()) { address branch_addr = target(branch_target); branch_optimized(cond, branch_addr); + } else if (branch_target.is_near()) { + z_brc(cond, branch_target); // Caller assures that the target will be in range for z_brc. } else { z_brcl(cond, branch_target); // Let's hope target is in range. Otherwise, we will abort at patch time. } @@ -1674,7 +1676,8 @@ void MacroAssembler::compare_and_branch_optimized(Register r1, bool has_sign) { address branch_origin = pc(); bool x2_imm8 = (has_sign && Immediate::is_simm8(x2)) || (!has_sign && Immediate::is_uimm8(x2)); - bool is_RelAddr16 = (branch_target.is_bound() && + bool is_RelAddr16 = branch_target.is_near() || + (branch_target.is_bound() && RelAddr::is_in_range_of_RelAddr16(target(branch_target), branch_origin)); unsigned int casenum = (len64?2:0)+(has_sign?0:1); @@ -1744,13 +1747,21 @@ void MacroAssembler::compare_and_branch_optimized(Register r1, Label& branch_target, bool len64, bool has_sign) { - unsigned int casenum = (len64?2:0)+(has_sign?0:1); + unsigned int casenum = (len64 ? 2 : 0) + (has_sign ? 0 : 1); if (branch_target.is_bound()) { address branch_addr = target(branch_target); compare_and_branch_optimized(r1, r2, cond, branch_addr, len64, has_sign); } else { - { + if (VM_Version::has_CompareBranch() && branch_target.is_near()) { + switch (casenum) { + case 0: z_crj( r1, r2, cond, branch_target); break; + case 1: z_clrj( r1, r2, cond, branch_target); break; + case 2: z_cgrj( r1, r2, cond, branch_target); break; + case 3: z_clgrj(r1, r2, cond, branch_target); break; + default: ShouldNotReachHere(); break; + } + } else { switch (casenum) { case 0: z_cr( r1, r2); break; case 1: z_clr(r1, r2); break; @@ -2741,11 +2752,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, BLOCK_COMMENT("lookup_interface_method {"); // Load start of itable entries into itable_entry_addr. - z_llgf(vtable_len, Address(recv_klass, InstanceKlass::vtable_length_offset())); + z_llgf(vtable_len, Address(recv_klass, Klass::vtable_length_offset())); z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); // Loop over all itable entries until desired interfaceOop(Rinterface) found. - const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); + const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), @@ -5927,8 +5938,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl * @param len register containing number of bytes * @param table register pointing to CRC table */ -void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool invertCRC) { +void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, Register data) { assert_different_registers(crc, buf, len, table, data); Label L_mainLoop, L_done; @@ -5938,20 +5948,12 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register z_ltr(len, len); z_brnh(L_done); - if (invertCRC) { - not_(crc, noreg, false); // ~c - } - bind(L_mainLoop); z_llgc(data, Address(buf, (intptr_t)0));// Current byte of input buffer (zero extended). Avoids garbage in upper half of register. add2reg(buf, mainLoop_stepping); // Advance buffer position. update_byte_crc32(crc, data, table); z_brct(len, L_mainLoop); // Iterate. - if (invertCRC) { - not_(crc, noreg, false); // ~c - } - bind(L_done); } @@ -5968,6 +5970,7 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab // c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ // crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] // #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + // Pre-calculate (constant) column offsets, use columns 4..7 for big-endian. const int ix0 = 4*(4*CRC32_COLUMN_SIZE); const int ix1 = 5*(4*CRC32_COLUMN_SIZE); const int ix2 = 6*(4*CRC32_COLUMN_SIZE); @@ -5986,17 +5989,12 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab rotate_then_insert(t1, t0, 56-2, 63-2, 2-16, true); // ((c >> 16) & 0xff) << 2 rotate_then_insert(t0, t0, 56-2, 63-2, 2-24, true); // ((c >> 24) & 0xff) << 2 - // Load pre-calculated table values. - // Use columns 4..7 for big-endian. - z_ly(t3, Address(table, t3, (intptr_t)ix0)); + // XOR indexed table values to calculate updated crc. z_ly(t2, Address(table, t2, (intptr_t)ix1)); - z_ly(t1, Address(table, t1, (intptr_t)ix2)); z_ly(t0, Address(table, t0, (intptr_t)ix3)); - - // Calculate new crc from table values. - z_xr(t2, t3); - z_xr(t0, t1); - z_xr(t0, t2); // Now crc contains the final checksum value. + z_xy(t2, Address(table, t3, (intptr_t)ix0)); + z_xy(t0, Address(table, t1, (intptr_t)ix2)); + z_xr(t0, t2); // Now t0 contains the updated CRC value. lgr_if_needed(crc, t0); } @@ -6009,7 +6007,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! */ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -6024,7 +6023,9 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len // The situation itself is detected and handled correctly by the conditional branches // following aghi(len, -stepping) and aghi(len, +stepping). - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } #if 0 { @@ -6039,7 +6040,7 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len rotate_then_insert(ctr, ctr, 62, 63, 0, true); // TODO: should set cc z_sgfr(len, ctr); // Remaining len after alignment. - update_byteLoop_crc32(crc, buf, ctr, table, data, false); + update_byteLoop_crc32(crc, buf, ctr, table, data); } #endif @@ -6047,21 +6048,23 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len z_srag(ctr, len, log_stepping); z_brnh(L_tail); - z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data. + z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data. rotate_then_insert(len, len, 64-log_stepping, 63, 0, true); // #bytes for tailLoop BIND(L_mainLoop); update_1word_crc32(crc, buf, table, 0, 0, crc, t1, t2, t3); update_1word_crc32(crc, buf, table, 4, mainLoop_stepping, crc, t1, t2, t3); - z_brct(ctr, L_mainLoop); // Iterate. + z_brct(ctr, L_mainLoop); // Iterate. - z_lrvr(crc, crc); // Revert byte order back to original. + z_lrvr(crc, crc); // Revert byte order back to original. // Process last few (<8) bytes of buffer. BIND(L_tail); - update_byteLoop_crc32(crc, buf, len, table, data, false); + update_byteLoop_crc32(crc, buf, len, table, data); - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } /** @@ -6073,7 +6076,8 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! */ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -6087,7 +6091,9 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len // The situation itself is detected and handled correctly by the conditional branches // following aghi(len, -stepping) and aghi(len, +stepping). - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } // Check for short (<4 bytes) buffer. z_srag(ctr, len, log_stepping); @@ -6099,13 +6105,16 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len BIND(L_mainLoop); update_1word_crc32(crc, buf, table, 0, mainLoop_stepping, crc, t1, t2, t3); z_brct(ctr, L_mainLoop); // Iterate. + z_lrvr(crc, crc); // Revert byte order back to original. // Process last few (<8) bytes of buffer. BIND(L_tail); - update_byteLoop_crc32(crc, buf, len, table, data, false); + update_byteLoop_crc32(crc, buf, len, table, data); - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } /** @@ -6115,22 +6124,51 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len * @param table register pointing to CRC table */ void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Register data = t0; - update_byteLoop_crc32(crc, buf, len, table, data, true); + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } + + update_byteLoop_crc32(crc, buf, len, table, data); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } -void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp) { +void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp, + bool invertCRC) { assert_different_registers(crc, buf, len, table, tmp); - not_(crc, noreg, false); // ~c + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } z_llgc(tmp, Address(buf, (intptr_t)0)); // Current byte of input buffer (zero extended). Avoids garbage in upper half of register. update_byte_crc32(crc, tmp, table); - not_(crc, noreg, false); // ~c + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } +} + +void MacroAssembler::kernel_crc32_singleByteReg(Register crc, Register val, Register table, + bool invertCRC) { + assert_different_registers(crc, val, table); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } + + update_byte_crc32(crc, val, table); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } // diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp index 2b4002a3bf4..7153c254398 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1011,22 +1011,35 @@ class MacroAssembler: public Assembler { int before = 0, int after = 0) PRODUCT_RETURN; // Emitters for CRC32 calculation. + // A note on invertCRC: + // Unfortunately, internal representation of crc differs between CRC32 and CRC32C. + // CRC32 holds it's current crc value in the externally visible representation. + // CRC32C holds it's current crc value in internal format, ready for updating. + // Thus, the crc value must be bit-flipped before updating it in the CRC32 case. + // In the CRC32C case, it must be bit-flipped when it is given to the outside world (getValue()). + // The bool invertCRC parameter indicates whether bit-flipping is required before updates. private: void fold_byte_crc32(Register crc, Register table, Register val, Register tmp); void fold_8bit_crc32(Register crc, Register table, Register tmp); + void update_byte_crc32( Register crc, Register val, Register table); void update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool invertCRC); + Register data); void update_1word_crc32(Register crc, Register buf, Register table, int bufDisp, int bufInc, Register t0, Register t1, Register t2, Register t3); public: - void update_byte_crc32( Register crc, Register val, Register table); - void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp); + void kernel_crc32_singleByteReg(Register crc, Register val, Register table, + bool invertCRC); + void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp, + bool invertCRC); void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); void kernel_crc32_1word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); void kernel_crc32_2word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); // Emitters for BigInteger.multiplyToLen intrinsic // note: length of result array (zlen) is passed on the stack diff --git a/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp b/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp deleted file mode 100644 index 8e7feacf527..00000000000 --- a/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/codeBuffer.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->klass_part()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size();. -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no releationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#undef __ -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - __ unimplemented(); -} diff --git a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp index e2f0d32cc8a..11f9222fa2e 100644 --- a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp +++ b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -73,7 +73,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); assert(temp_reg != Z_R0 && // Is used as base register! temp_reg != noreg && temp2_reg != noreg, "need valid registers!"); @@ -200,10 +200,13 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(method_temp); - // The following assumes that a method is normally compressed in the vmtarget field. + __ load_heap_oop(method_temp, + Address(method_temp, + NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(method_temp); __ z_lg(method_temp, Address(method_temp, - NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // Make sure recv is already on stack. @@ -371,7 +374,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method(Z_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -424,7 +428,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ z_lg(Z_method, member_vmtarget); + __ load_heap_oop(Z_method, member_vmtarget); + __ z_lg(Z_method, vmtarget_method); method_is_live = true; break; @@ -432,7 +437,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ z_lg(Z_method, member_vmtarget); + __ load_heap_oop(Z_method, member_vmtarget); + __ z_lg(Z_method, vmtarget_method); method_is_live = true; break; diff --git a/hotspot/src/cpu/s390/vm/s390.ad b/hotspot/src/cpu/s390/vm/s390.ad index fd188525c46..39d661b65c9 100644 --- a/hotspot/src/cpu/s390/vm/s390.ad +++ b/hotspot/src/cpu/s390/vm/s390.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2016 SAP SE. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -1562,7 +1562,7 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg. -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize == 8 && size == 8, ""); return Op_RegL; } @@ -1577,7 +1577,7 @@ const int Matcher::min_vector_size(const BasicType bt) { return max_vector_size(bt); // Same as max. } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { fatal("vector shift is not supported"); return Node::NotAMachineReg; } @@ -6768,6 +6768,7 @@ instruct sllI_reg_imm(iRegI dst, iRegI src, immI nbits) %{ format %{ "SLL $dst,$src,$nbits\t# use RISC-like SLLG also for int" %} ins_encode %{ int Nbit = $nbits$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sllg($dst$$Register, $src$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6841,6 +6842,7 @@ instruct sraI_reg_imm(iRegI dst, immI src, flagsReg cr) %{ format %{ "SRA $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sra($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6893,6 +6895,7 @@ instruct srlI_reg_imm(iRegI dst, immI src) %{ format %{ "SRL $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_srl($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); diff --git a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp index be107222636..bcadfaf3919 100644 --- a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -623,26 +623,6 @@ class StubGenerator: public StubCodeGenerator { #define __ (Verbose ? (_masm->block_comment(FILE_AND_LINE),_masm):_masm)-> #endif - //---------------------------------------------------------------------- - // The following routine generates a subroutine to throw an asynchronous - // UnknownError when an unsafe access gets a fault that could not be - // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.) - // - // Arguments: - // trapping PC: ?? - // - // Results: - // Posts an asynchronous exception, skips the trapping instruction. - // - address generate_handler_for_unsafe_access() { - StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access"); - { - address start = __ pc(); - __ unimplemented("StubRoutines::handler_for_unsafe_access", 86); - return start; - } - } - // Support for uint StubRoutine::zarch::partial_subtype_check(Klass // sub, Klass super); // @@ -2330,26 +2310,25 @@ class StubGenerator: public StubCodeGenerator { } - - // Arguments: - // Z_ARG1 - int crc - // Z_ARG2 - byte* buf - // Z_ARG3 - int length (of buffer) - // - // Result: - // Z_RET - int crc result - // - // Compute CRC32 function. - address generate_CRC32_updateBytes(const char* name) { - __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", name); - unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + /** + * Arguments: + * + * Inputs: + * Z_ARG1 - int crc + * Z_ARG2 - byte* buf + * Z_ARG3 - int length (of buffer) + * + * Result: + * Z_RET - int crc result + **/ + // Compute CRC function (generic, for all polynomials). + void generate_CRC_updateBytes(const char* name, Register table, bool invertCRC) { // arguments to kernel_crc32: Register crc = Z_ARG1; // Current checksum, preset by caller or result from previous call, int. Register data = Z_ARG2; // source byte array Register dataLen = Z_ARG3; // #bytes to process, int - Register table = Z_ARG4; // crc table address +// Register table = Z_ARG4; // crc table address. Preloaded and passed in by caller. const Register t0 = Z_R10; // work reg for kernel* emitters const Register t1 = Z_R11; // work reg for kernel* emitters const Register t2 = Z_R12; // work reg for kernel* emitters @@ -2361,16 +2340,50 @@ class StubGenerator: public StubCodeGenerator { // Crc used as int. __ z_llgfr(dataLen, dataLen); - StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_stmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, invertCRC); __ z_lmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 back from stack. __ resize_frame(+(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_llgfr(Z_RET, crc); // Updated crc is function result. No copying required, just zero upper 32 bits. __ z_br(Z_R14); // Result already in Z_RET == Z_ARG1. + } + + + // Compute CRC32 function. + address generate_CRC32_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + assert(UseCRC32Intrinsics, "should not generate this stub (%s) with CRC32 intrinsics disabled", name); + + BLOCK_COMMENT("CRC32_updateBytes {"); + Register table = Z_ARG4; // crc32 table address. + StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); + + generate_CRC_updateBytes(name, table, true); + BLOCK_COMMENT("} CRC32_updateBytes"); + + return __ addr_at(start_off); + } + + + // Compute CRC32C function. + address generate_CRC32C_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + assert(UseCRC32CIntrinsics, "should not generate this stub (%s) with CRC32C intrinsics disabled", name); + + BLOCK_COMMENT("CRC32C_updateBytes {"); + Register table = Z_ARG4; // crc32c table address. + StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); + + generate_CRC_updateBytes(name, table, false); + BLOCK_COMMENT("} CRC32C_updateBytes"); return __ addr_at(start_off); } @@ -2441,9 +2454,13 @@ class StubGenerator: public StubCodeGenerator { // Entry points that are platform specific. if (UseCRC32Intrinsics) { - // We have no CRC32 table on z/Architecture. - StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table; - StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); + StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table; + StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); + } + + if (UseCRC32CIntrinsics) { + StubRoutines::_crc32c_table_addr = (address)StubRoutines::zarch::_crc32c_table; + StubRoutines::_updateBytesCRC32C = generate_CRC32C_updateBytes("CRC32C_updateBytes"); } // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. @@ -2461,8 +2478,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); - StubRoutines::zarch::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access(); - // Support for verify_oop (must happen after universe_init). StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine(); diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp index 8c60ae04350..ab167d9030f 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,6 @@ // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. -address StubRoutines::zarch::_handler_for_unsafe_access_entry = NULL; - address StubRoutines::zarch::_partial_subtype_check = NULL; // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. @@ -44,14 +42,15 @@ int StubRoutines::zarch::_atomic_memory_operation_lock = StubRoutines::zarch::un #define __ masm-> -void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { +void StubRoutines::zarch::generate_load_absolute_address(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents) { + __ load_absolute_address(table, table_addr); - __ load_absolute_address(table, StubRoutines::_crc_table_adr); #ifdef ASSERT - assert(_crc_table_adr != NULL, "CRC lookup table address must be initialized by now"); + assert(table_addr != NULL, "CRC lookup table address must be initialized by now"); + assert(*((uint32_t*)(table_addr+4)) == (uint32_t)table_contents, "Bad CRC lookup table: 0x%8.8x, expected 0x%8.8x", *((uint32_t*)(table_addr+4)), (uint32_t)table_contents); { Label L; - __ load_const_optimized(Z_R0, StubRoutines::_crc_table_adr); + __ load_const_optimized(Z_R0, table_addr); __ z_cgr(table, Z_R0); // safety net __ z_bre(L); __ z_illtrap(); @@ -60,7 +59,7 @@ void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Reg } { Label L; - __ load_const_optimized(Z_R0, 0x77073096UL); + __ load_const_optimized(Z_R0, table_contents); // crc_table: data @ offset(4) __ z_cl(Z_R0, Address(table, 4)); // safety net __ z_bre(L); __ z_l(Z_R0, Address(table, 4)); // Load data from memory, we know the constant we compared against. @@ -71,6 +70,17 @@ void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Reg #endif } +void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { + const uint64_t table_contents = 0x77073096UL; // required contents of table[1] + generate_load_absolute_address(masm, table, StubRoutines::_crc_table_adr, table_contents); +} + +void StubRoutines::zarch::generate_load_crc32c_table_addr(MacroAssembler* masm, Register table) { + const uint64_t table_contents = 0xf26b8303UL; // required contents of table[1] + generate_load_absolute_address(masm, table, StubRoutines::_crc32c_table_addr, table_contents); +} + + // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. void StubRoutines::zarch::generate_load_trot_table_addr(MacroAssembler* masm, Register table) { @@ -130,440 +140,590 @@ jlong StubRoutines::zarch::_trot_table[TROT_COLUMN_SIZE] = { }; -// crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h juint StubRoutines::zarch::_crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef CRC32_BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; + /* polyBits = 7976584769 0x00000001db710641L, shifted = 0xedb88320 */ + /* CRC32 table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32 table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U + /* 8 */ , 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U + /* 16 */ , 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U + /* 24 */ , 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U + /* 32 */ , 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU + /* 40 */ , 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U + /* 48 */ , 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU + /* 56 */ , 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU + /* 64 */ , 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U + /* 72 */ , 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U + /* 80 */ , 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U + /* 88 */ , 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U + /* 96 */ , 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU + /* 104 */ , 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U + /* 112 */ , 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU + /* 120 */ , 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU + /* 128 */ , 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U + /* 136 */ , 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U + /* 144 */ , 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U + /* 152 */ , 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U + /* 160 */ , 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU + /* 168 */ , 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U + /* 176 */ , 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU + /* 184 */ , 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU + /* 192 */ , 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U + /* 200 */ , 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U + /* 208 */ , 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U + /* 216 */ , 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U + /* 224 */ , 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU + /* 232 */ , 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U + /* 240 */ , 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU + /* 248 */ , 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU + } + #ifdef CRC32_BYFOUR + , + /* CRC32 table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, 0x7d77f445U, 0x565aa786U, 0x4f4196c7U + /* 8 */ , 0xc8d98a08U, 0xd1c2bb49U, 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, 0x87981ccfU + /* 16 */ , 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U + /* 24 */ , 0x821b9859U, 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, 0xd4413fdfU, 0xcd5a0e9eU + /* 32 */ , 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U + /* 40 */ , 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, 0x202a5aefU, 0x0b07092cU, 0x121c386dU + /* 48 */ , 0xdf4636f3U, 0xc65d07b2U, 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, 0x9007a034U + /* 56 */ , 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU + /* 64 */ , 0xf0794f05U, 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, 0xa623e883U, 0xbf38d9c2U + /* 72 */ , 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU + /* 80 */ , 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, 0xc7cca911U, 0xece1fad2U, 0xf5facb93U + /* 88 */ , 0x7262d75cU, 0x6b79e61dU, 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, 0x3d23419bU + /* 96 */ , 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U + /* 104 */ , 0xad24e1afU, 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, 0xfb7e4629U, 0xe2657768U + /* 112 */ , 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U + /* 120 */ , 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U + /* 128 */ , 0x3b83984bU, 0x2298a90aU, 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, 0x74c20e8cU + /* 136 */ , 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U + /* 144 */ , 0x71418a1aU, 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, 0x271b2d9cU, 0x3e001cddU + /* 152 */ , 0xb9980012U, 0xa0833153U, 0x8bae6290U, 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U + /* 160 */ , 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU + /* 168 */ , 0x66de36e1U, 0x7fc507a0U, 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, 0x299fa026U + /* 176 */ , 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU + /* 184 */ , 0x2c1c24b0U, 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, 0x7a468336U, 0x635db277U + /* 192 */ , 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U + /* 200 */ , 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U + /* 208 */ , 0x8138c51fU, 0x9823f45eU, 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, 0xce7953d8U + /* 216 */ , 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U + /* 224 */ , 0x5e7ef3ecU, 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, 0x0824546aU, 0x113f652bU + /* 232 */ , 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U + /* 240 */ , 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU + /* 248 */ , 0xdc656bb5U, 0xc57e5af4U, 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, 0x9324fd72U + } + , + /* CRC32 table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U + /* 8 */ , 0x0e1351b8U, 0x0fd13b8fU, 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, 0x0b5c473dU + /* 16 */ , 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U + /* 24 */ , 0x1235f2c8U, 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, 0x16b88e7aU, 0x177ae44dU + /* 32 */ , 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U + /* 40 */ , 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, 0x3095d5b3U, 0x32d36beaU, 0x331101ddU + /* 48 */ , 0x246be590U, 0x25a98fa7U, 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, 0x2124f315U + /* 56 */ , 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU + /* 64 */ , 0x709a8dc0U, 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, 0x7417f172U, 0x75d59b45U + /* 72 */ , 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU + /* 80 */ , 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, 0x6a77ec5bU, 0x68315202U, 0x69f33835U + /* 88 */ , 0x62af7f08U, 0x636d153fU, 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, 0x67e0698dU + /* 96 */ , 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U + /* 104 */ , 0x46c49a98U, 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, 0x4249e62aU, 0x438b8c1dU + /* 112 */ , 0x54f16850U, 0x55330267U, 0x5775bc3eU, 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U + /* 120 */ , 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU + /* 128 */ , 0xe1351b80U, 0xe0f771b7U, 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, 0xe47a0d05U + /* 136 */ , 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU + /* 144 */ , 0xfd13b8f0U, 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, 0xf99ec442U, 0xf85cae75U + /* 152 */ , 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU + /* 160 */ , 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U + /* 168 */ , 0xd76b0cd8U, 0xd6a966efU, 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, 0xd2241a5dU + /* 176 */ , 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U + /* 184 */ , 0xcb4dafa8U, 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, 0xcfc0d31aU, 0xce02b92dU + /* 192 */ , 0x91af9640U, 0x906dfc77U, 0x922b422eU, 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U + /* 200 */ , 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU + /* 208 */ , 0x8d893530U, 0x8c4b5f07U, 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, 0x88c623b5U + /* 216 */ , 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU + /* 224 */ , 0xa9e2d0a0U, 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, 0xad6fac12U, 0xacadc625U + /* 232 */ , 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU + /* 240 */ , 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U + /* 248 */ , 0xbbd72268U, 0xba15485fU, 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, 0xbe9834edU + } + , + /* CRC32 table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, 0x37def032U, 0x256b5fdcU, 0x9dd738b9U + /* 8 */ , 0xc5b428efU, 0x7d084f8aU, 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, 0x58631056U + /* 16 */ , 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U + /* 24 */ , 0x95ad7f70U, 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, 0xb0c620acU, 0x087a47c9U + /* 32 */ , 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U + /* 40 */ , 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, 0x525877e3U, 0x40edd80dU, 0xf851bf68U + /* 48 */ , 0xf02bf8a1U, 0x48979fc4U, 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, 0x6dfcc018U + /* 56 */ , 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U + /* 64 */ , 0x9b14583dU, 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, 0xbe7f07e1U, 0x06c36084U + /* 72 */ , 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU + /* 80 */ , 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, 0xfcd3ff90U, 0xee66507eU, 0x56da371bU + /* 88 */ , 0x0eb9274dU, 0xb6054028U, 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, 0x936e1ff4U + /* 96 */ , 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU + /* 104 */ , 0xfe92dfecU, 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, 0xdbf98030U, 0x6345e755U + /* 112 */ , 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U + /* 120 */ , 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, 0x99557841U, 0x8be0d7afU, 0x335cb0caU + /* 128 */ , 0xed59b63bU, 0x55e5d15eU, 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, 0x708e8e82U + /* 136 */ , 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU + /* 144 */ , 0xbd40e1a4U, 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, 0x982bbe78U, 0x2097d91dU + /* 152 */ , 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U + /* 160 */ , 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU + /* 168 */ , 0x88df31eaU, 0x3063568fU, 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, 0x15080953U + /* 176 */ , 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U + /* 184 */ , 0xd8c66675U, 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, 0xfdad39a9U, 0x45115eccU + /* 192 */ , 0x764dee06U, 0xcef18963U, 0xdc44268dU, 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU + /* 200 */ , 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, 0x842736dbU, 0x96929935U, 0x2e2efe50U + /* 208 */ , 0x2654b999U, 0x9ee8defcU, 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, 0xbb838120U + /* 216 */ , 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU + /* 224 */ , 0xd67f4138U, 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, 0xf3141ee4U, 0x4ba87981U + /* 232 */ , 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU + /* 240 */ , 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU + /* 248 */ , 0x43d23e48U, 0xfb6e592dU, 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, 0xde0506f1U + } + , + /* CRC32 table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x96300777U, 0x2c610eeeU, 0xba510999U, 0x19c46d07U, 0x8ff46a70U, 0x35a563e9U, 0xa395649eU + /* 8 */ , 0x3288db0eU, 0xa4b8dc79U, 0x1ee9d5e0U, 0x88d9d297U, 0x2b4cb609U, 0xbd7cb17eU, 0x072db8e7U, 0x911dbf90U + /* 16 */ , 0x6410b71dU, 0xf220b06aU, 0x4871b9f3U, 0xde41be84U, 0x7dd4da1aU, 0xebe4dd6dU, 0x51b5d4f4U, 0xc785d383U + /* 24 */ , 0x56986c13U, 0xc0a86b64U, 0x7af962fdU, 0xecc9658aU, 0x4f5c0114U, 0xd96c0663U, 0x633d0ffaU, 0xf50d088dU + /* 32 */ , 0xc8206e3bU, 0x5e10694cU, 0xe44160d5U, 0x727167a2U, 0xd1e4033cU, 0x47d4044bU, 0xfd850dd2U, 0x6bb50aa5U + /* 40 */ , 0xfaa8b535U, 0x6c98b242U, 0xd6c9bbdbU, 0x40f9bcacU, 0xe36cd832U, 0x755cdf45U, 0xcf0dd6dcU, 0x593dd1abU + /* 48 */ , 0xac30d926U, 0x3a00de51U, 0x8051d7c8U, 0x1661d0bfU, 0xb5f4b421U, 0x23c4b356U, 0x9995bacfU, 0x0fa5bdb8U + /* 56 */ , 0x9eb80228U, 0x0888055fU, 0xb2d90cc6U, 0x24e90bb1U, 0x877c6f2fU, 0x114c6858U, 0xab1d61c1U, 0x3d2d66b6U + /* 64 */ , 0x9041dc76U, 0x0671db01U, 0xbc20d298U, 0x2a10d5efU, 0x8985b171U, 0x1fb5b606U, 0xa5e4bf9fU, 0x33d4b8e8U + /* 72 */ , 0xa2c90778U, 0x34f9000fU, 0x8ea80996U, 0x18980ee1U, 0xbb0d6a7fU, 0x2d3d6d08U, 0x976c6491U, 0x015c63e6U + /* 80 */ , 0xf4516b6bU, 0x62616c1cU, 0xd8306585U, 0x4e0062f2U, 0xed95066cU, 0x7ba5011bU, 0xc1f40882U, 0x57c40ff5U + /* 88 */ , 0xc6d9b065U, 0x50e9b712U, 0xeab8be8bU, 0x7c88b9fcU, 0xdf1ddd62U, 0x492dda15U, 0xf37cd38cU, 0x654cd4fbU + /* 96 */ , 0x5861b24dU, 0xce51b53aU, 0x7400bca3U, 0xe230bbd4U, 0x41a5df4aU, 0xd795d83dU, 0x6dc4d1a4U, 0xfbf4d6d3U + /* 104 */ , 0x6ae96943U, 0xfcd96e34U, 0x468867adU, 0xd0b860daU, 0x732d0444U, 0xe51d0333U, 0x5f4c0aaaU, 0xc97c0dddU + /* 112 */ , 0x3c710550U, 0xaa410227U, 0x10100bbeU, 0x86200cc9U, 0x25b56857U, 0xb3856f20U, 0x09d466b9U, 0x9fe461ceU + /* 120 */ , 0x0ef9de5eU, 0x98c9d929U, 0x2298d0b0U, 0xb4a8d7c7U, 0x173db359U, 0x810db42eU, 0x3b5cbdb7U, 0xad6cbac0U + /* 128 */ , 0x2083b8edU, 0xb6b3bf9aU, 0x0ce2b603U, 0x9ad2b174U, 0x3947d5eaU, 0xaf77d29dU, 0x1526db04U, 0x8316dc73U + /* 136 */ , 0x120b63e3U, 0x843b6494U, 0x3e6a6d0dU, 0xa85a6a7aU, 0x0bcf0ee4U, 0x9dff0993U, 0x27ae000aU, 0xb19e077dU + /* 144 */ , 0x44930ff0U, 0xd2a30887U, 0x68f2011eU, 0xfec20669U, 0x5d5762f7U, 0xcb676580U, 0x71366c19U, 0xe7066b6eU + /* 152 */ , 0x761bd4feU, 0xe02bd389U, 0x5a7ada10U, 0xcc4add67U, 0x6fdfb9f9U, 0xf9efbe8eU, 0x43beb717U, 0xd58eb060U + /* 160 */ , 0xe8a3d6d6U, 0x7e93d1a1U, 0xc4c2d838U, 0x52f2df4fU, 0xf167bbd1U, 0x6757bca6U, 0xdd06b53fU, 0x4b36b248U + /* 168 */ , 0xda2b0dd8U, 0x4c1b0aafU, 0xf64a0336U, 0x607a0441U, 0xc3ef60dfU, 0x55df67a8U, 0xef8e6e31U, 0x79be6946U + /* 176 */ , 0x8cb361cbU, 0x1a8366bcU, 0xa0d26f25U, 0x36e26852U, 0x95770cccU, 0x03470bbbU, 0xb9160222U, 0x2f260555U + /* 184 */ , 0xbe3bbac5U, 0x280bbdb2U, 0x925ab42bU, 0x046ab35cU, 0xa7ffd7c2U, 0x31cfd0b5U, 0x8b9ed92cU, 0x1daede5bU + /* 192 */ , 0xb0c2649bU, 0x26f263ecU, 0x9ca36a75U, 0x0a936d02U, 0xa906099cU, 0x3f360eebU, 0x85670772U, 0x13570005U + /* 200 */ , 0x824abf95U, 0x147ab8e2U, 0xae2bb17bU, 0x381bb60cU, 0x9b8ed292U, 0x0dbed5e5U, 0xb7efdc7cU, 0x21dfdb0bU + /* 208 */ , 0xd4d2d386U, 0x42e2d4f1U, 0xf8b3dd68U, 0x6e83da1fU, 0xcd16be81U, 0x5b26b9f6U, 0xe177b06fU, 0x7747b718U + /* 216 */ , 0xe65a0888U, 0x706a0fffU, 0xca3b0666U, 0x5c0b0111U, 0xff9e658fU, 0x69ae62f8U, 0xd3ff6b61U, 0x45cf6c16U + /* 224 */ , 0x78e20aa0U, 0xeed20dd7U, 0x5483044eU, 0xc2b30339U, 0x612667a7U, 0xf71660d0U, 0x4d476949U, 0xdb776e3eU + /* 232 */ , 0x4a6ad1aeU, 0xdc5ad6d9U, 0x660bdf40U, 0xf03bd837U, 0x53aebca9U, 0xc59ebbdeU, 0x7fcfb247U, 0xe9ffb530U + /* 240 */ , 0x1cf2bdbdU, 0x8ac2bacaU, 0x3093b353U, 0xa6a3b424U, 0x0536d0baU, 0x9306d7cdU, 0x2957de54U, 0xbf67d923U + /* 248 */ , 0x2e7a66b3U, 0xb84a61c4U, 0x021b685dU, 0x942b6f2aU, 0x37be0bb4U, 0xa18e0cc3U, 0x1bdf055aU, 0x8def022dU + } + , + /* CRC32 table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x41311b19U, 0x82623632U, 0xc3532d2bU, 0x04c56c64U, 0x45f4777dU, 0x86a75a56U, 0xc796414fU + /* 8 */ , 0x088ad9c8U, 0x49bbc2d1U, 0x8ae8effaU, 0xcbd9f4e3U, 0x0c4fb5acU, 0x4d7eaeb5U, 0x8e2d839eU, 0xcf1c9887U + /* 16 */ , 0x5112c24aU, 0x1023d953U, 0xd370f478U, 0x9241ef61U, 0x55d7ae2eU, 0x14e6b537U, 0xd7b5981cU, 0x96848305U + /* 24 */ , 0x59981b82U, 0x18a9009bU, 0xdbfa2db0U, 0x9acb36a9U, 0x5d5d77e6U, 0x1c6c6cffU, 0xdf3f41d4U, 0x9e0e5acdU + /* 32 */ , 0xa2248495U, 0xe3159f8cU, 0x2046b2a7U, 0x6177a9beU, 0xa6e1e8f1U, 0xe7d0f3e8U, 0x2483dec3U, 0x65b2c5daU + /* 40 */ , 0xaaae5d5dU, 0xeb9f4644U, 0x28cc6b6fU, 0x69fd7076U, 0xae6b3139U, 0xef5a2a20U, 0x2c09070bU, 0x6d381c12U + /* 48 */ , 0xf33646dfU, 0xb2075dc6U, 0x715470edU, 0x30656bf4U, 0xf7f32abbU, 0xb6c231a2U, 0x75911c89U, 0x34a00790U + /* 56 */ , 0xfbbc9f17U, 0xba8d840eU, 0x79dea925U, 0x38efb23cU, 0xff79f373U, 0xbe48e86aU, 0x7d1bc541U, 0x3c2ade58U + /* 64 */ , 0x054f79f0U, 0x447e62e9U, 0x872d4fc2U, 0xc61c54dbU, 0x018a1594U, 0x40bb0e8dU, 0x83e823a6U, 0xc2d938bfU + /* 72 */ , 0x0dc5a038U, 0x4cf4bb21U, 0x8fa7960aU, 0xce968d13U, 0x0900cc5cU, 0x4831d745U, 0x8b62fa6eU, 0xca53e177U + /* 80 */ , 0x545dbbbaU, 0x156ca0a3U, 0xd63f8d88U, 0x970e9691U, 0x5098d7deU, 0x11a9ccc7U, 0xd2fae1ecU, 0x93cbfaf5U + /* 88 */ , 0x5cd76272U, 0x1de6796bU, 0xdeb55440U, 0x9f844f59U, 0x58120e16U, 0x1923150fU, 0xda703824U, 0x9b41233dU + /* 96 */ , 0xa76bfd65U, 0xe65ae67cU, 0x2509cb57U, 0x6438d04eU, 0xa3ae9101U, 0xe29f8a18U, 0x21cca733U, 0x60fdbc2aU + /* 104 */ , 0xafe124adU, 0xeed03fb4U, 0x2d83129fU, 0x6cb20986U, 0xab2448c9U, 0xea1553d0U, 0x29467efbU, 0x687765e2U + /* 112 */ , 0xf6793f2fU, 0xb7482436U, 0x741b091dU, 0x352a1204U, 0xf2bc534bU, 0xb38d4852U, 0x70de6579U, 0x31ef7e60U + /* 120 */ , 0xfef3e6e7U, 0xbfc2fdfeU, 0x7c91d0d5U, 0x3da0cbccU, 0xfa368a83U, 0xbb07919aU, 0x7854bcb1U, 0x3965a7a8U + /* 128 */ , 0x4b98833bU, 0x0aa99822U, 0xc9fab509U, 0x88cbae10U, 0x4f5def5fU, 0x0e6cf446U, 0xcd3fd96dU, 0x8c0ec274U + /* 136 */ , 0x43125af3U, 0x022341eaU, 0xc1706cc1U, 0x804177d8U, 0x47d73697U, 0x06e62d8eU, 0xc5b500a5U, 0x84841bbcU + /* 144 */ , 0x1a8a4171U, 0x5bbb5a68U, 0x98e87743U, 0xd9d96c5aU, 0x1e4f2d15U, 0x5f7e360cU, 0x9c2d1b27U, 0xdd1c003eU + /* 152 */ , 0x120098b9U, 0x533183a0U, 0x9062ae8bU, 0xd153b592U, 0x16c5f4ddU, 0x57f4efc4U, 0x94a7c2efU, 0xd596d9f6U + /* 160 */ , 0xe9bc07aeU, 0xa88d1cb7U, 0x6bde319cU, 0x2aef2a85U, 0xed796bcaU, 0xac4870d3U, 0x6f1b5df8U, 0x2e2a46e1U + /* 168 */ , 0xe136de66U, 0xa007c57fU, 0x6354e854U, 0x2265f34dU, 0xe5f3b202U, 0xa4c2a91bU, 0x67918430U, 0x26a09f29U + /* 176 */ , 0xb8aec5e4U, 0xf99fdefdU, 0x3accf3d6U, 0x7bfde8cfU, 0xbc6ba980U, 0xfd5ab299U, 0x3e099fb2U, 0x7f3884abU + /* 184 */ , 0xb0241c2cU, 0xf1150735U, 0x32462a1eU, 0x73773107U, 0xb4e17048U, 0xf5d06b51U, 0x3683467aU, 0x77b25d63U + /* 192 */ , 0x4ed7facbU, 0x0fe6e1d2U, 0xccb5ccf9U, 0x8d84d7e0U, 0x4a1296afU, 0x0b238db6U, 0xc870a09dU, 0x8941bb84U + /* 200 */ , 0x465d2303U, 0x076c381aU, 0xc43f1531U, 0x850e0e28U, 0x42984f67U, 0x03a9547eU, 0xc0fa7955U, 0x81cb624cU + /* 208 */ , 0x1fc53881U, 0x5ef42398U, 0x9da70eb3U, 0xdc9615aaU, 0x1b0054e5U, 0x5a314ffcU, 0x996262d7U, 0xd85379ceU + /* 216 */ , 0x174fe149U, 0x567efa50U, 0x952dd77bU, 0xd41ccc62U, 0x138a8d2dU, 0x52bb9634U, 0x91e8bb1fU, 0xd0d9a006U + /* 224 */ , 0xecf37e5eU, 0xadc26547U, 0x6e91486cU, 0x2fa05375U, 0xe836123aU, 0xa9070923U, 0x6a542408U, 0x2b653f11U + /* 232 */ , 0xe479a796U, 0xa548bc8fU, 0x661b91a4U, 0x272a8abdU, 0xe0bccbf2U, 0xa18dd0ebU, 0x62defdc0U, 0x23efe6d9U + /* 240 */ , 0xbde1bc14U, 0xfcd0a70dU, 0x3f838a26U, 0x7eb2913fU, 0xb924d070U, 0xf815cb69U, 0x3b46e642U, 0x7a77fd5bU + /* 248 */ , 0xb56b65dcU, 0xf45a7ec5U, 0x370953eeU, 0x763848f7U, 0xb1ae09b8U, 0xf09f12a1U, 0x33cc3f8aU, 0x72fd2493U + } + , + /* CRC32 table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x376ac201U, 0x6ed48403U, 0x59be4602U, 0xdca80907U, 0xebc2cb06U, 0xb27c8d04U, 0x85164f05U + /* 8 */ , 0xb851130eU, 0x8f3bd10fU, 0xd685970dU, 0xe1ef550cU, 0x64f91a09U, 0x5393d808U, 0x0a2d9e0aU, 0x3d475c0bU + /* 16 */ , 0x70a3261cU, 0x47c9e41dU, 0x1e77a21fU, 0x291d601eU, 0xac0b2f1bU, 0x9b61ed1aU, 0xc2dfab18U, 0xf5b56919U + /* 24 */ , 0xc8f23512U, 0xff98f713U, 0xa626b111U, 0x914c7310U, 0x145a3c15U, 0x2330fe14U, 0x7a8eb816U, 0x4de47a17U + /* 32 */ , 0xe0464d38U, 0xd72c8f39U, 0x8e92c93bU, 0xb9f80b3aU, 0x3cee443fU, 0x0b84863eU, 0x523ac03cU, 0x6550023dU + /* 40 */ , 0x58175e36U, 0x6f7d9c37U, 0x36c3da35U, 0x01a91834U, 0x84bf5731U, 0xb3d59530U, 0xea6bd332U, 0xdd011133U + /* 48 */ , 0x90e56b24U, 0xa78fa925U, 0xfe31ef27U, 0xc95b2d26U, 0x4c4d6223U, 0x7b27a022U, 0x2299e620U, 0x15f32421U + /* 56 */ , 0x28b4782aU, 0x1fdeba2bU, 0x4660fc29U, 0x710a3e28U, 0xf41c712dU, 0xc376b32cU, 0x9ac8f52eU, 0xada2372fU + /* 64 */ , 0xc08d9a70U, 0xf7e75871U, 0xae591e73U, 0x9933dc72U, 0x1c259377U, 0x2b4f5176U, 0x72f11774U, 0x459bd575U + /* 72 */ , 0x78dc897eU, 0x4fb64b7fU, 0x16080d7dU, 0x2162cf7cU, 0xa4748079U, 0x931e4278U, 0xcaa0047aU, 0xfdcac67bU + /* 80 */ , 0xb02ebc6cU, 0x87447e6dU, 0xdefa386fU, 0xe990fa6eU, 0x6c86b56bU, 0x5bec776aU, 0x02523168U, 0x3538f369U + /* 88 */ , 0x087faf62U, 0x3f156d63U, 0x66ab2b61U, 0x51c1e960U, 0xd4d7a665U, 0xe3bd6464U, 0xba032266U, 0x8d69e067U + /* 96 */ , 0x20cbd748U, 0x17a11549U, 0x4e1f534bU, 0x7975914aU, 0xfc63de4fU, 0xcb091c4eU, 0x92b75a4cU, 0xa5dd984dU + /* 104 */ , 0x989ac446U, 0xaff00647U, 0xf64e4045U, 0xc1248244U, 0x4432cd41U, 0x73580f40U, 0x2ae64942U, 0x1d8c8b43U + /* 112 */ , 0x5068f154U, 0x67023355U, 0x3ebc7557U, 0x09d6b756U, 0x8cc0f853U, 0xbbaa3a52U, 0xe2147c50U, 0xd57ebe51U + /* 120 */ , 0xe839e25aU, 0xdf53205bU, 0x86ed6659U, 0xb187a458U, 0x3491eb5dU, 0x03fb295cU, 0x5a456f5eU, 0x6d2fad5fU + /* 128 */ , 0x801b35e1U, 0xb771f7e0U, 0xeecfb1e2U, 0xd9a573e3U, 0x5cb33ce6U, 0x6bd9fee7U, 0x3267b8e5U, 0x050d7ae4U + /* 136 */ , 0x384a26efU, 0x0f20e4eeU, 0x569ea2ecU, 0x61f460edU, 0xe4e22fe8U, 0xd388ede9U, 0x8a36abebU, 0xbd5c69eaU + /* 144 */ , 0xf0b813fdU, 0xc7d2d1fcU, 0x9e6c97feU, 0xa90655ffU, 0x2c101afaU, 0x1b7ad8fbU, 0x42c49ef9U, 0x75ae5cf8U + /* 152 */ , 0x48e900f3U, 0x7f83c2f2U, 0x263d84f0U, 0x115746f1U, 0x944109f4U, 0xa32bcbf5U, 0xfa958df7U, 0xcdff4ff6U + /* 160 */ , 0x605d78d9U, 0x5737bad8U, 0x0e89fcdaU, 0x39e33edbU, 0xbcf571deU, 0x8b9fb3dfU, 0xd221f5ddU, 0xe54b37dcU + /* 168 */ , 0xd80c6bd7U, 0xef66a9d6U, 0xb6d8efd4U, 0x81b22dd5U, 0x04a462d0U, 0x33cea0d1U, 0x6a70e6d3U, 0x5d1a24d2U + /* 176 */ , 0x10fe5ec5U, 0x27949cc4U, 0x7e2adac6U, 0x494018c7U, 0xcc5657c2U, 0xfb3c95c3U, 0xa282d3c1U, 0x95e811c0U + /* 184 */ , 0xa8af4dcbU, 0x9fc58fcaU, 0xc67bc9c8U, 0xf1110bc9U, 0x740744ccU, 0x436d86cdU, 0x1ad3c0cfU, 0x2db902ceU + /* 192 */ , 0x4096af91U, 0x77fc6d90U, 0x2e422b92U, 0x1928e993U, 0x9c3ea696U, 0xab546497U, 0xf2ea2295U, 0xc580e094U + /* 200 */ , 0xf8c7bc9fU, 0xcfad7e9eU, 0x9613389cU, 0xa179fa9dU, 0x246fb598U, 0x13057799U, 0x4abb319bU, 0x7dd1f39aU + /* 208 */ , 0x3035898dU, 0x075f4b8cU, 0x5ee10d8eU, 0x698bcf8fU, 0xec9d808aU, 0xdbf7428bU, 0x82490489U, 0xb523c688U + /* 216 */ , 0x88649a83U, 0xbf0e5882U, 0xe6b01e80U, 0xd1dadc81U, 0x54cc9384U, 0x63a65185U, 0x3a181787U, 0x0d72d586U + /* 224 */ , 0xa0d0e2a9U, 0x97ba20a8U, 0xce0466aaU, 0xf96ea4abU, 0x7c78ebaeU, 0x4b1229afU, 0x12ac6fadU, 0x25c6adacU + /* 232 */ , 0x1881f1a7U, 0x2feb33a6U, 0x765575a4U, 0x413fb7a5U, 0xc429f8a0U, 0xf3433aa1U, 0xaafd7ca3U, 0x9d97bea2U + /* 240 */ , 0xd073c4b5U, 0xe71906b4U, 0xbea740b6U, 0x89cd82b7U, 0x0cdbcdb2U, 0x3bb10fb3U, 0x620f49b1U, 0x55658bb0U + /* 248 */ , 0x6822d7bbU, 0x5f4815baU, 0x06f653b8U, 0x319c91b9U, 0xb48adebcU, 0x83e01cbdU, 0xda5e5abfU, 0xed3498beU + } + , + /* CRC32 table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x6567bcb8U, 0x8bc809aaU, 0xeeafb512U, 0x5797628fU, 0x32f0de37U, 0xdc5f6b25U, 0xb938d79dU + /* 8 */ , 0xef28b4c5U, 0x8a4f087dU, 0x64e0bd6fU, 0x018701d7U, 0xb8bfd64aU, 0xddd86af2U, 0x3377dfe0U, 0x56106358U + /* 16 */ , 0x9f571950U, 0xfa30a5e8U, 0x149f10faU, 0x71f8ac42U, 0xc8c07bdfU, 0xada7c767U, 0x43087275U, 0x266fcecdU + /* 24 */ , 0x707fad95U, 0x1518112dU, 0xfbb7a43fU, 0x9ed01887U, 0x27e8cf1aU, 0x428f73a2U, 0xac20c6b0U, 0xc9477a08U + /* 32 */ , 0x3eaf32a0U, 0x5bc88e18U, 0xb5673b0aU, 0xd00087b2U, 0x6938502fU, 0x0c5fec97U, 0xe2f05985U, 0x8797e53dU + /* 40 */ , 0xd1878665U, 0xb4e03addU, 0x5a4f8fcfU, 0x3f283377U, 0x8610e4eaU, 0xe3775852U, 0x0dd8ed40U, 0x68bf51f8U + /* 48 */ , 0xa1f82bf0U, 0xc49f9748U, 0x2a30225aU, 0x4f579ee2U, 0xf66f497fU, 0x9308f5c7U, 0x7da740d5U, 0x18c0fc6dU + /* 56 */ , 0x4ed09f35U, 0x2bb7238dU, 0xc518969fU, 0xa07f2a27U, 0x1947fdbaU, 0x7c204102U, 0x928ff410U, 0xf7e848a8U + /* 64 */ , 0x3d58149bU, 0x583fa823U, 0xb6901d31U, 0xd3f7a189U, 0x6acf7614U, 0x0fa8caacU, 0xe1077fbeU, 0x8460c306U + /* 72 */ , 0xd270a05eU, 0xb7171ce6U, 0x59b8a9f4U, 0x3cdf154cU, 0x85e7c2d1U, 0xe0807e69U, 0x0e2fcb7bU, 0x6b4877c3U + /* 80 */ , 0xa20f0dcbU, 0xc768b173U, 0x29c70461U, 0x4ca0b8d9U, 0xf5986f44U, 0x90ffd3fcU, 0x7e5066eeU, 0x1b37da56U + /* 88 */ , 0x4d27b90eU, 0x284005b6U, 0xc6efb0a4U, 0xa3880c1cU, 0x1ab0db81U, 0x7fd76739U, 0x9178d22bU, 0xf41f6e93U + /* 96 */ , 0x03f7263bU, 0x66909a83U, 0x883f2f91U, 0xed589329U, 0x546044b4U, 0x3107f80cU, 0xdfa84d1eU, 0xbacff1a6U + /* 104 */ , 0xecdf92feU, 0x89b82e46U, 0x67179b54U, 0x027027ecU, 0xbb48f071U, 0xde2f4cc9U, 0x3080f9dbU, 0x55e74563U + /* 112 */ , 0x9ca03f6bU, 0xf9c783d3U, 0x176836c1U, 0x720f8a79U, 0xcb375de4U, 0xae50e15cU, 0x40ff544eU, 0x2598e8f6U + /* 120 */ , 0x73888baeU, 0x16ef3716U, 0xf8408204U, 0x9d273ebcU, 0x241fe921U, 0x41785599U, 0xafd7e08bU, 0xcab05c33U + /* 128 */ , 0x3bb659edU, 0x5ed1e555U, 0xb07e5047U, 0xd519ecffU, 0x6c213b62U, 0x094687daU, 0xe7e932c8U, 0x828e8e70U + /* 136 */ , 0xd49eed28U, 0xb1f95190U, 0x5f56e482U, 0x3a31583aU, 0x83098fa7U, 0xe66e331fU, 0x08c1860dU, 0x6da63ab5U + /* 144 */ , 0xa4e140bdU, 0xc186fc05U, 0x2f294917U, 0x4a4ef5afU, 0xf3762232U, 0x96119e8aU, 0x78be2b98U, 0x1dd99720U + /* 152 */ , 0x4bc9f478U, 0x2eae48c0U, 0xc001fdd2U, 0xa566416aU, 0x1c5e96f7U, 0x79392a4fU, 0x97969f5dU, 0xf2f123e5U + /* 160 */ , 0x05196b4dU, 0x607ed7f5U, 0x8ed162e7U, 0xebb6de5fU, 0x528e09c2U, 0x37e9b57aU, 0xd9460068U, 0xbc21bcd0U + /* 168 */ , 0xea31df88U, 0x8f566330U, 0x61f9d622U, 0x049e6a9aU, 0xbda6bd07U, 0xd8c101bfU, 0x366eb4adU, 0x53090815U + /* 176 */ , 0x9a4e721dU, 0xff29cea5U, 0x11867bb7U, 0x74e1c70fU, 0xcdd91092U, 0xa8beac2aU, 0x46111938U, 0x2376a580U + /* 184 */ , 0x7566c6d8U, 0x10017a60U, 0xfeaecf72U, 0x9bc973caU, 0x22f1a457U, 0x479618efU, 0xa939adfdU, 0xcc5e1145U + /* 192 */ , 0x06ee4d76U, 0x6389f1ceU, 0x8d2644dcU, 0xe841f864U, 0x51792ff9U, 0x341e9341U, 0xdab12653U, 0xbfd69aebU + /* 200 */ , 0xe9c6f9b3U, 0x8ca1450bU, 0x620ef019U, 0x07694ca1U, 0xbe519b3cU, 0xdb362784U, 0x35999296U, 0x50fe2e2eU + /* 208 */ , 0x99b95426U, 0xfcdee89eU, 0x12715d8cU, 0x7716e134U, 0xce2e36a9U, 0xab498a11U, 0x45e63f03U, 0x208183bbU + /* 216 */ , 0x7691e0e3U, 0x13f65c5bU, 0xfd59e949U, 0x983e55f1U, 0x2106826cU, 0x44613ed4U, 0xaace8bc6U, 0xcfa9377eU + /* 224 */ , 0x38417fd6U, 0x5d26c36eU, 0xb389767cU, 0xd6eecac4U, 0x6fd61d59U, 0x0ab1a1e1U, 0xe41e14f3U, 0x8179a84bU + /* 232 */ , 0xd769cb13U, 0xb20e77abU, 0x5ca1c2b9U, 0x39c67e01U, 0x80fea99cU, 0xe5991524U, 0x0b36a036U, 0x6e511c8eU + /* 240 */ , 0xa7166686U, 0xc271da3eU, 0x2cde6f2cU, 0x49b9d394U, 0xf0810409U, 0x95e6b8b1U, 0x7b490da3U, 0x1e2eb11bU + /* 248 */ , 0x483ed243U, 0x2d596efbU, 0xc3f6dbe9U, 0xa6916751U, 0x1fa9b0ccU, 0x7ace0c74U, 0x9461b966U, 0xf10605deU + } + #endif + }; + +juint StubRoutines::zarch::_crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { + /* polyBits = 4394350321 0x0000000105ec76f1L, shifted = 0x82f63b78 */ + /* CRC32C table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32C table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xf26b8303U, 0xe13b70f7U, 0x1350f3f4U, 0xc79a971fU, 0x35f1141cU, 0x26a1e7e8U, 0xd4ca64ebU + /* 8 */ , 0x8ad958cfU, 0x78b2dbccU, 0x6be22838U, 0x9989ab3bU, 0x4d43cfd0U, 0xbf284cd3U, 0xac78bf27U, 0x5e133c24U + /* 16 */ , 0x105ec76fU, 0xe235446cU, 0xf165b798U, 0x030e349bU, 0xd7c45070U, 0x25afd373U, 0x36ff2087U, 0xc494a384U + /* 24 */ , 0x9a879fa0U, 0x68ec1ca3U, 0x7bbcef57U, 0x89d76c54U, 0x5d1d08bfU, 0xaf768bbcU, 0xbc267848U, 0x4e4dfb4bU + /* 32 */ , 0x20bd8edeU, 0xd2d60dddU, 0xc186fe29U, 0x33ed7d2aU, 0xe72719c1U, 0x154c9ac2U, 0x061c6936U, 0xf477ea35U + /* 40 */ , 0xaa64d611U, 0x580f5512U, 0x4b5fa6e6U, 0xb93425e5U, 0x6dfe410eU, 0x9f95c20dU, 0x8cc531f9U, 0x7eaeb2faU + /* 48 */ , 0x30e349b1U, 0xc288cab2U, 0xd1d83946U, 0x23b3ba45U, 0xf779deaeU, 0x05125dadU, 0x1642ae59U, 0xe4292d5aU + /* 56 */ , 0xba3a117eU, 0x4851927dU, 0x5b016189U, 0xa96ae28aU, 0x7da08661U, 0x8fcb0562U, 0x9c9bf696U, 0x6ef07595U + /* 64 */ , 0x417b1dbcU, 0xb3109ebfU, 0xa0406d4bU, 0x522bee48U, 0x86e18aa3U, 0x748a09a0U, 0x67dafa54U, 0x95b17957U + /* 72 */ , 0xcba24573U, 0x39c9c670U, 0x2a993584U, 0xd8f2b687U, 0x0c38d26cU, 0xfe53516fU, 0xed03a29bU, 0x1f682198U + /* 80 */ , 0x5125dad3U, 0xa34e59d0U, 0xb01eaa24U, 0x42752927U, 0x96bf4dccU, 0x64d4cecfU, 0x77843d3bU, 0x85efbe38U + /* 88 */ , 0xdbfc821cU, 0x2997011fU, 0x3ac7f2ebU, 0xc8ac71e8U, 0x1c661503U, 0xee0d9600U, 0xfd5d65f4U, 0x0f36e6f7U + /* 96 */ , 0x61c69362U, 0x93ad1061U, 0x80fde395U, 0x72966096U, 0xa65c047dU, 0x5437877eU, 0x4767748aU, 0xb50cf789U + /* 104 */ , 0xeb1fcbadU, 0x197448aeU, 0x0a24bb5aU, 0xf84f3859U, 0x2c855cb2U, 0xdeeedfb1U, 0xcdbe2c45U, 0x3fd5af46U + /* 112 */ , 0x7198540dU, 0x83f3d70eU, 0x90a324faU, 0x62c8a7f9U, 0xb602c312U, 0x44694011U, 0x5739b3e5U, 0xa55230e6U + /* 120 */ , 0xfb410cc2U, 0x092a8fc1U, 0x1a7a7c35U, 0xe811ff36U, 0x3cdb9bddU, 0xceb018deU, 0xdde0eb2aU, 0x2f8b6829U + /* 128 */ , 0x82f63b78U, 0x709db87bU, 0x63cd4b8fU, 0x91a6c88cU, 0x456cac67U, 0xb7072f64U, 0xa457dc90U, 0x563c5f93U + /* 136 */ , 0x082f63b7U, 0xfa44e0b4U, 0xe9141340U, 0x1b7f9043U, 0xcfb5f4a8U, 0x3dde77abU, 0x2e8e845fU, 0xdce5075cU + /* 144 */ , 0x92a8fc17U, 0x60c37f14U, 0x73938ce0U, 0x81f80fe3U, 0x55326b08U, 0xa759e80bU, 0xb4091bffU, 0x466298fcU + /* 152 */ , 0x1871a4d8U, 0xea1a27dbU, 0xf94ad42fU, 0x0b21572cU, 0xdfeb33c7U, 0x2d80b0c4U, 0x3ed04330U, 0xccbbc033U + /* 160 */ , 0xa24bb5a6U, 0x502036a5U, 0x4370c551U, 0xb11b4652U, 0x65d122b9U, 0x97baa1baU, 0x84ea524eU, 0x7681d14dU + /* 168 */ , 0x2892ed69U, 0xdaf96e6aU, 0xc9a99d9eU, 0x3bc21e9dU, 0xef087a76U, 0x1d63f975U, 0x0e330a81U, 0xfc588982U + /* 176 */ , 0xb21572c9U, 0x407ef1caU, 0x532e023eU, 0xa145813dU, 0x758fe5d6U, 0x87e466d5U, 0x94b49521U, 0x66df1622U + /* 184 */ , 0x38cc2a06U, 0xcaa7a905U, 0xd9f75af1U, 0x2b9cd9f2U, 0xff56bd19U, 0x0d3d3e1aU, 0x1e6dcdeeU, 0xec064eedU + /* 192 */ , 0xc38d26c4U, 0x31e6a5c7U, 0x22b65633U, 0xd0ddd530U, 0x0417b1dbU, 0xf67c32d8U, 0xe52cc12cU, 0x1747422fU + /* 200 */ , 0x49547e0bU, 0xbb3ffd08U, 0xa86f0efcU, 0x5a048dffU, 0x8ecee914U, 0x7ca56a17U, 0x6ff599e3U, 0x9d9e1ae0U + /* 208 */ , 0xd3d3e1abU, 0x21b862a8U, 0x32e8915cU, 0xc083125fU, 0x144976b4U, 0xe622f5b7U, 0xf5720643U, 0x07198540U + /* 216 */ , 0x590ab964U, 0xab613a67U, 0xb831c993U, 0x4a5a4a90U, 0x9e902e7bU, 0x6cfbad78U, 0x7fab5e8cU, 0x8dc0dd8fU + /* 224 */ , 0xe330a81aU, 0x115b2b19U, 0x020bd8edU, 0xf0605beeU, 0x24aa3f05U, 0xd6c1bc06U, 0xc5914ff2U, 0x37faccf1U + /* 232 */ , 0x69e9f0d5U, 0x9b8273d6U, 0x88d28022U, 0x7ab90321U, 0xae7367caU, 0x5c18e4c9U, 0x4f48173dU, 0xbd23943eU + /* 240 */ , 0xf36e6f75U, 0x0105ec76U, 0x12551f82U, 0xe03e9c81U, 0x34f4f86aU, 0xc69f7b69U, 0xd5cf889dU, 0x27a40b9eU + /* 248 */ , 0x79b737baU, 0x8bdcb4b9U, 0x988c474dU, 0x6ae7c44eU, 0xbe2da0a5U, 0x4c4623a6U, 0x5f16d052U, 0xad7d5351U + } + #ifdef CRC32_BYFOUR + , + /* CRC32C table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x13a29877U, 0x274530eeU, 0x34e7a899U, 0x4e8a61dcU, 0x5d28f9abU, 0x69cf5132U, 0x7a6dc945U + /* 8 */ , 0x9d14c3b8U, 0x8eb65bcfU, 0xba51f356U, 0xa9f36b21U, 0xd39ea264U, 0xc03c3a13U, 0xf4db928aU, 0xe7790afdU + /* 16 */ , 0x3fc5f181U, 0x2c6769f6U, 0x1880c16fU, 0x0b225918U, 0x714f905dU, 0x62ed082aU, 0x560aa0b3U, 0x45a838c4U + /* 24 */ , 0xa2d13239U, 0xb173aa4eU, 0x859402d7U, 0x96369aa0U, 0xec5b53e5U, 0xfff9cb92U, 0xcb1e630bU, 0xd8bcfb7cU + /* 32 */ , 0x7f8be302U, 0x6c297b75U, 0x58ced3ecU, 0x4b6c4b9bU, 0x310182deU, 0x22a31aa9U, 0x1644b230U, 0x05e62a47U + /* 40 */ , 0xe29f20baU, 0xf13db8cdU, 0xc5da1054U, 0xd6788823U, 0xac154166U, 0xbfb7d911U, 0x8b507188U, 0x98f2e9ffU + /* 48 */ , 0x404e1283U, 0x53ec8af4U, 0x670b226dU, 0x74a9ba1aU, 0x0ec4735fU, 0x1d66eb28U, 0x298143b1U, 0x3a23dbc6U + /* 56 */ , 0xdd5ad13bU, 0xcef8494cU, 0xfa1fe1d5U, 0xe9bd79a2U, 0x93d0b0e7U, 0x80722890U, 0xb4958009U, 0xa737187eU + /* 64 */ , 0xff17c604U, 0xecb55e73U, 0xd852f6eaU, 0xcbf06e9dU, 0xb19da7d8U, 0xa23f3fafU, 0x96d89736U, 0x857a0f41U + /* 72 */ , 0x620305bcU, 0x71a19dcbU, 0x45463552U, 0x56e4ad25U, 0x2c896460U, 0x3f2bfc17U, 0x0bcc548eU, 0x186eccf9U + /* 80 */ , 0xc0d23785U, 0xd370aff2U, 0xe797076bU, 0xf4359f1cU, 0x8e585659U, 0x9dface2eU, 0xa91d66b7U, 0xbabffec0U + /* 88 */ , 0x5dc6f43dU, 0x4e646c4aU, 0x7a83c4d3U, 0x69215ca4U, 0x134c95e1U, 0x00ee0d96U, 0x3409a50fU, 0x27ab3d78U + /* 96 */ , 0x809c2506U, 0x933ebd71U, 0xa7d915e8U, 0xb47b8d9fU, 0xce1644daU, 0xddb4dcadU, 0xe9537434U, 0xfaf1ec43U + /* 104 */ , 0x1d88e6beU, 0x0e2a7ec9U, 0x3acdd650U, 0x296f4e27U, 0x53028762U, 0x40a01f15U, 0x7447b78cU, 0x67e52ffbU + /* 112 */ , 0xbf59d487U, 0xacfb4cf0U, 0x981ce469U, 0x8bbe7c1eU, 0xf1d3b55bU, 0xe2712d2cU, 0xd69685b5U, 0xc5341dc2U + /* 120 */ , 0x224d173fU, 0x31ef8f48U, 0x050827d1U, 0x16aabfa6U, 0x6cc776e3U, 0x7f65ee94U, 0x4b82460dU, 0x5820de7aU + /* 128 */ , 0xfbc3faf9U, 0xe861628eU, 0xdc86ca17U, 0xcf245260U, 0xb5499b25U, 0xa6eb0352U, 0x920cabcbU, 0x81ae33bcU + /* 136 */ , 0x66d73941U, 0x7575a136U, 0x419209afU, 0x523091d8U, 0x285d589dU, 0x3bffc0eaU, 0x0f186873U, 0x1cbaf004U + /* 144 */ , 0xc4060b78U, 0xd7a4930fU, 0xe3433b96U, 0xf0e1a3e1U, 0x8a8c6aa4U, 0x992ef2d3U, 0xadc95a4aU, 0xbe6bc23dU + /* 152 */ , 0x5912c8c0U, 0x4ab050b7U, 0x7e57f82eU, 0x6df56059U, 0x1798a91cU, 0x043a316bU, 0x30dd99f2U, 0x237f0185U + /* 160 */ , 0x844819fbU, 0x97ea818cU, 0xa30d2915U, 0xb0afb162U, 0xcac27827U, 0xd960e050U, 0xed8748c9U, 0xfe25d0beU + /* 168 */ , 0x195cda43U, 0x0afe4234U, 0x3e19eaadU, 0x2dbb72daU, 0x57d6bb9fU, 0x447423e8U, 0x70938b71U, 0x63311306U + /* 176 */ , 0xbb8de87aU, 0xa82f700dU, 0x9cc8d894U, 0x8f6a40e3U, 0xf50789a6U, 0xe6a511d1U, 0xd242b948U, 0xc1e0213fU + /* 184 */ , 0x26992bc2U, 0x353bb3b5U, 0x01dc1b2cU, 0x127e835bU, 0x68134a1eU, 0x7bb1d269U, 0x4f567af0U, 0x5cf4e287U + /* 192 */ , 0x04d43cfdU, 0x1776a48aU, 0x23910c13U, 0x30339464U, 0x4a5e5d21U, 0x59fcc556U, 0x6d1b6dcfU, 0x7eb9f5b8U + /* 200 */ , 0x99c0ff45U, 0x8a626732U, 0xbe85cfabU, 0xad2757dcU, 0xd74a9e99U, 0xc4e806eeU, 0xf00fae77U, 0xe3ad3600U + /* 208 */ , 0x3b11cd7cU, 0x28b3550bU, 0x1c54fd92U, 0x0ff665e5U, 0x759baca0U, 0x663934d7U, 0x52de9c4eU, 0x417c0439U + /* 216 */ , 0xa6050ec4U, 0xb5a796b3U, 0x81403e2aU, 0x92e2a65dU, 0xe88f6f18U, 0xfb2df76fU, 0xcfca5ff6U, 0xdc68c781U + /* 224 */ , 0x7b5fdfffU, 0x68fd4788U, 0x5c1aef11U, 0x4fb87766U, 0x35d5be23U, 0x26772654U, 0x12908ecdU, 0x013216baU + /* 232 */ , 0xe64b1c47U, 0xf5e98430U, 0xc10e2ca9U, 0xd2acb4deU, 0xa8c17d9bU, 0xbb63e5ecU, 0x8f844d75U, 0x9c26d502U + /* 240 */ , 0x449a2e7eU, 0x5738b609U, 0x63df1e90U, 0x707d86e7U, 0x0a104fa2U, 0x19b2d7d5U, 0x2d557f4cU, 0x3ef7e73bU + /* 248 */ , 0xd98eedc6U, 0xca2c75b1U, 0xfecbdd28U, 0xed69455fU, 0x97048c1aU, 0x84a6146dU, 0xb041bcf4U, 0xa3e32483U + } + , + /* CRC32C table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xa541927eU, 0x4f6f520dU, 0xea2ec073U, 0x9edea41aU, 0x3b9f3664U, 0xd1b1f617U, 0x74f06469U + /* 8 */ , 0x38513ec5U, 0x9d10acbbU, 0x773e6cc8U, 0xd27ffeb6U, 0xa68f9adfU, 0x03ce08a1U, 0xe9e0c8d2U, 0x4ca15aacU + /* 16 */ , 0x70a27d8aU, 0xd5e3eff4U, 0x3fcd2f87U, 0x9a8cbdf9U, 0xee7cd990U, 0x4b3d4beeU, 0xa1138b9dU, 0x045219e3U + /* 24 */ , 0x48f3434fU, 0xedb2d131U, 0x079c1142U, 0xa2dd833cU, 0xd62de755U, 0x736c752bU, 0x9942b558U, 0x3c032726U + /* 32 */ , 0xe144fb14U, 0x4405696aU, 0xae2ba919U, 0x0b6a3b67U, 0x7f9a5f0eU, 0xdadbcd70U, 0x30f50d03U, 0x95b49f7dU + /* 40 */ , 0xd915c5d1U, 0x7c5457afU, 0x967a97dcU, 0x333b05a2U, 0x47cb61cbU, 0xe28af3b5U, 0x08a433c6U, 0xade5a1b8U + /* 48 */ , 0x91e6869eU, 0x34a714e0U, 0xde89d493U, 0x7bc846edU, 0x0f382284U, 0xaa79b0faU, 0x40577089U, 0xe516e2f7U + /* 56 */ , 0xa9b7b85bU, 0x0cf62a25U, 0xe6d8ea56U, 0x43997828U, 0x37691c41U, 0x92288e3fU, 0x78064e4cU, 0xdd47dc32U + /* 64 */ , 0xc76580d9U, 0x622412a7U, 0x880ad2d4U, 0x2d4b40aaU, 0x59bb24c3U, 0xfcfab6bdU, 0x16d476ceU, 0xb395e4b0U + /* 72 */ , 0xff34be1cU, 0x5a752c62U, 0xb05bec11U, 0x151a7e6fU, 0x61ea1a06U, 0xc4ab8878U, 0x2e85480bU, 0x8bc4da75U + /* 80 */ , 0xb7c7fd53U, 0x12866f2dU, 0xf8a8af5eU, 0x5de93d20U, 0x29195949U, 0x8c58cb37U, 0x66760b44U, 0xc337993aU + /* 88 */ , 0x8f96c396U, 0x2ad751e8U, 0xc0f9919bU, 0x65b803e5U, 0x1148678cU, 0xb409f5f2U, 0x5e273581U, 0xfb66a7ffU + /* 96 */ , 0x26217bcdU, 0x8360e9b3U, 0x694e29c0U, 0xcc0fbbbeU, 0xb8ffdfd7U, 0x1dbe4da9U, 0xf7908ddaU, 0x52d11fa4U + /* 104 */ , 0x1e704508U, 0xbb31d776U, 0x511f1705U, 0xf45e857bU, 0x80aee112U, 0x25ef736cU, 0xcfc1b31fU, 0x6a802161U + /* 112 */ , 0x56830647U, 0xf3c29439U, 0x19ec544aU, 0xbcadc634U, 0xc85da25dU, 0x6d1c3023U, 0x8732f050U, 0x2273622eU + /* 120 */ , 0x6ed23882U, 0xcb93aafcU, 0x21bd6a8fU, 0x84fcf8f1U, 0xf00c9c98U, 0x554d0ee6U, 0xbf63ce95U, 0x1a225cebU + /* 128 */ , 0x8b277743U, 0x2e66e53dU, 0xc448254eU, 0x6109b730U, 0x15f9d359U, 0xb0b84127U, 0x5a968154U, 0xffd7132aU + /* 136 */ , 0xb3764986U, 0x1637dbf8U, 0xfc191b8bU, 0x595889f5U, 0x2da8ed9cU, 0x88e97fe2U, 0x62c7bf91U, 0xc7862defU + /* 144 */ , 0xfb850ac9U, 0x5ec498b7U, 0xb4ea58c4U, 0x11abcabaU, 0x655baed3U, 0xc01a3cadU, 0x2a34fcdeU, 0x8f756ea0U + /* 152 */ , 0xc3d4340cU, 0x6695a672U, 0x8cbb6601U, 0x29faf47fU, 0x5d0a9016U, 0xf84b0268U, 0x1265c21bU, 0xb7245065U + /* 160 */ , 0x6a638c57U, 0xcf221e29U, 0x250cde5aU, 0x804d4c24U, 0xf4bd284dU, 0x51fcba33U, 0xbbd27a40U, 0x1e93e83eU + /* 168 */ , 0x5232b292U, 0xf77320ecU, 0x1d5de09fU, 0xb81c72e1U, 0xccec1688U, 0x69ad84f6U, 0x83834485U, 0x26c2d6fbU + /* 176 */ , 0x1ac1f1ddU, 0xbf8063a3U, 0x55aea3d0U, 0xf0ef31aeU, 0x841f55c7U, 0x215ec7b9U, 0xcb7007caU, 0x6e3195b4U + /* 184 */ , 0x2290cf18U, 0x87d15d66U, 0x6dff9d15U, 0xc8be0f6bU, 0xbc4e6b02U, 0x190ff97cU, 0xf321390fU, 0x5660ab71U + /* 192 */ , 0x4c42f79aU, 0xe90365e4U, 0x032da597U, 0xa66c37e9U, 0xd29c5380U, 0x77ddc1feU, 0x9df3018dU, 0x38b293f3U + /* 200 */ , 0x7413c95fU, 0xd1525b21U, 0x3b7c9b52U, 0x9e3d092cU, 0xeacd6d45U, 0x4f8cff3bU, 0xa5a23f48U, 0x00e3ad36U + /* 208 */ , 0x3ce08a10U, 0x99a1186eU, 0x738fd81dU, 0xd6ce4a63U, 0xa23e2e0aU, 0x077fbc74U, 0xed517c07U, 0x4810ee79U + /* 216 */ , 0x04b1b4d5U, 0xa1f026abU, 0x4bdee6d8U, 0xee9f74a6U, 0x9a6f10cfU, 0x3f2e82b1U, 0xd50042c2U, 0x7041d0bcU + /* 224 */ , 0xad060c8eU, 0x08479ef0U, 0xe2695e83U, 0x4728ccfdU, 0x33d8a894U, 0x96993aeaU, 0x7cb7fa99U, 0xd9f668e7U + /* 232 */ , 0x9557324bU, 0x3016a035U, 0xda386046U, 0x7f79f238U, 0x0b899651U, 0xaec8042fU, 0x44e6c45cU, 0xe1a75622U + /* 240 */ , 0xdda47104U, 0x78e5e37aU, 0x92cb2309U, 0x378ab177U, 0x437ad51eU, 0xe63b4760U, 0x0c158713U, 0xa954156dU + /* 248 */ , 0xe5f54fc1U, 0x40b4ddbfU, 0xaa9a1dccU, 0x0fdb8fb2U, 0x7b2bebdbU, 0xde6a79a5U, 0x3444b9d6U, 0x91052ba8U + } + , + /* CRC32C table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xdd45aab8U, 0xbf672381U, 0x62228939U, 0x7b2231f3U, 0xa6679b4bU, 0xc4451272U, 0x1900b8caU + /* 8 */ , 0xf64463e6U, 0x2b01c95eU, 0x49234067U, 0x9466eadfU, 0x8d665215U, 0x5023f8adU, 0x32017194U, 0xef44db2cU + /* 16 */ , 0xe964b13dU, 0x34211b85U, 0x560392bcU, 0x8b463804U, 0x924680ceU, 0x4f032a76U, 0x2d21a34fU, 0xf06409f7U + /* 24 */ , 0x1f20d2dbU, 0xc2657863U, 0xa047f15aU, 0x7d025be2U, 0x6402e328U, 0xb9474990U, 0xdb65c0a9U, 0x06206a11U + /* 32 */ , 0xd725148bU, 0x0a60be33U, 0x6842370aU, 0xb5079db2U, 0xac072578U, 0x71428fc0U, 0x136006f9U, 0xce25ac41U + /* 40 */ , 0x2161776dU, 0xfc24ddd5U, 0x9e0654ecU, 0x4343fe54U, 0x5a43469eU, 0x8706ec26U, 0xe524651fU, 0x3861cfa7U + /* 48 */ , 0x3e41a5b6U, 0xe3040f0eU, 0x81268637U, 0x5c632c8fU, 0x45639445U, 0x98263efdU, 0xfa04b7c4U, 0x27411d7cU + /* 56 */ , 0xc805c650U, 0x15406ce8U, 0x7762e5d1U, 0xaa274f69U, 0xb327f7a3U, 0x6e625d1bU, 0x0c40d422U, 0xd1057e9aU + /* 64 */ , 0xaba65fe7U, 0x76e3f55fU, 0x14c17c66U, 0xc984d6deU, 0xd0846e14U, 0x0dc1c4acU, 0x6fe34d95U, 0xb2a6e72dU + /* 72 */ , 0x5de23c01U, 0x80a796b9U, 0xe2851f80U, 0x3fc0b538U, 0x26c00df2U, 0xfb85a74aU, 0x99a72e73U, 0x44e284cbU + /* 80 */ , 0x42c2eedaU, 0x9f874462U, 0xfda5cd5bU, 0x20e067e3U, 0x39e0df29U, 0xe4a57591U, 0x8687fca8U, 0x5bc25610U + /* 88 */ , 0xb4868d3cU, 0x69c32784U, 0x0be1aebdU, 0xd6a40405U, 0xcfa4bccfU, 0x12e11677U, 0x70c39f4eU, 0xad8635f6U + /* 96 */ , 0x7c834b6cU, 0xa1c6e1d4U, 0xc3e468edU, 0x1ea1c255U, 0x07a17a9fU, 0xdae4d027U, 0xb8c6591eU, 0x6583f3a6U + /* 104 */ , 0x8ac7288aU, 0x57828232U, 0x35a00b0bU, 0xe8e5a1b3U, 0xf1e51979U, 0x2ca0b3c1U, 0x4e823af8U, 0x93c79040U + /* 112 */ , 0x95e7fa51U, 0x48a250e9U, 0x2a80d9d0U, 0xf7c57368U, 0xeec5cba2U, 0x3380611aU, 0x51a2e823U, 0x8ce7429bU + /* 120 */ , 0x63a399b7U, 0xbee6330fU, 0xdcc4ba36U, 0x0181108eU, 0x1881a844U, 0xc5c402fcU, 0xa7e68bc5U, 0x7aa3217dU + /* 128 */ , 0x52a0c93fU, 0x8fe56387U, 0xedc7eabeU, 0x30824006U, 0x2982f8ccU, 0xf4c75274U, 0x96e5db4dU, 0x4ba071f5U + /* 136 */ , 0xa4e4aad9U, 0x79a10061U, 0x1b838958U, 0xc6c623e0U, 0xdfc69b2aU, 0x02833192U, 0x60a1b8abU, 0xbde41213U + /* 144 */ , 0xbbc47802U, 0x6681d2baU, 0x04a35b83U, 0xd9e6f13bU, 0xc0e649f1U, 0x1da3e349U, 0x7f816a70U, 0xa2c4c0c8U + /* 152 */ , 0x4d801be4U, 0x90c5b15cU, 0xf2e73865U, 0x2fa292ddU, 0x36a22a17U, 0xebe780afU, 0x89c50996U, 0x5480a32eU + /* 160 */ , 0x8585ddb4U, 0x58c0770cU, 0x3ae2fe35U, 0xe7a7548dU, 0xfea7ec47U, 0x23e246ffU, 0x41c0cfc6U, 0x9c85657eU + /* 168 */ , 0x73c1be52U, 0xae8414eaU, 0xcca69dd3U, 0x11e3376bU, 0x08e38fa1U, 0xd5a62519U, 0xb784ac20U, 0x6ac10698U + /* 176 */ , 0x6ce16c89U, 0xb1a4c631U, 0xd3864f08U, 0x0ec3e5b0U, 0x17c35d7aU, 0xca86f7c2U, 0xa8a47efbU, 0x75e1d443U + /* 184 */ , 0x9aa50f6fU, 0x47e0a5d7U, 0x25c22ceeU, 0xf8878656U, 0xe1873e9cU, 0x3cc29424U, 0x5ee01d1dU, 0x83a5b7a5U + /* 192 */ , 0xf90696d8U, 0x24433c60U, 0x4661b559U, 0x9b241fe1U, 0x8224a72bU, 0x5f610d93U, 0x3d4384aaU, 0xe0062e12U + /* 200 */ , 0x0f42f53eU, 0xd2075f86U, 0xb025d6bfU, 0x6d607c07U, 0x7460c4cdU, 0xa9256e75U, 0xcb07e74cU, 0x16424df4U + /* 208 */ , 0x106227e5U, 0xcd278d5dU, 0xaf050464U, 0x7240aedcU, 0x6b401616U, 0xb605bcaeU, 0xd4273597U, 0x09629f2fU + /* 216 */ , 0xe6264403U, 0x3b63eebbU, 0x59416782U, 0x8404cd3aU, 0x9d0475f0U, 0x4041df48U, 0x22635671U, 0xff26fcc9U + /* 224 */ , 0x2e238253U, 0xf36628ebU, 0x9144a1d2U, 0x4c010b6aU, 0x5501b3a0U, 0x88441918U, 0xea669021U, 0x37233a99U + /* 232 */ , 0xd867e1b5U, 0x05224b0dU, 0x6700c234U, 0xba45688cU, 0xa345d046U, 0x7e007afeU, 0x1c22f3c7U, 0xc167597fU + /* 240 */ , 0xc747336eU, 0x1a0299d6U, 0x782010efU, 0xa565ba57U, 0xbc65029dU, 0x6120a825U, 0x0302211cU, 0xde478ba4U + /* 248 */ , 0x31035088U, 0xec46fa30U, 0x8e647309U, 0x5321d9b1U, 0x4a21617bU, 0x9764cbc3U, 0xf54642faU, 0x2803e842U + } + , + /* CRC32C table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x03836bf2U, 0xf7703be1U, 0xf4f35013U, 0x1f979ac7U, 0x1c14f135U, 0xe8e7a126U, 0xeb64cad4U + /* 8 */ , 0xcf58d98aU, 0xccdbb278U, 0x3828e26bU, 0x3bab8999U, 0xd0cf434dU, 0xd34c28bfU, 0x27bf78acU, 0x243c135eU + /* 16 */ , 0x6fc75e10U, 0x6c4435e2U, 0x98b765f1U, 0x9b340e03U, 0x7050c4d7U, 0x73d3af25U, 0x8720ff36U, 0x84a394c4U + /* 24 */ , 0xa09f879aU, 0xa31cec68U, 0x57efbc7bU, 0x546cd789U, 0xbf081d5dU, 0xbc8b76afU, 0x487826bcU, 0x4bfb4d4eU + /* 32 */ , 0xde8ebd20U, 0xdd0dd6d2U, 0x29fe86c1U, 0x2a7ded33U, 0xc11927e7U, 0xc29a4c15U, 0x36691c06U, 0x35ea77f4U + /* 40 */ , 0x11d664aaU, 0x12550f58U, 0xe6a65f4bU, 0xe52534b9U, 0x0e41fe6dU, 0x0dc2959fU, 0xf931c58cU, 0xfab2ae7eU + /* 48 */ , 0xb149e330U, 0xb2ca88c2U, 0x4639d8d1U, 0x45bab323U, 0xaede79f7U, 0xad5d1205U, 0x59ae4216U, 0x5a2d29e4U + /* 56 */ , 0x7e113abaU, 0x7d925148U, 0x8961015bU, 0x8ae26aa9U, 0x6186a07dU, 0x6205cb8fU, 0x96f69b9cU, 0x9575f06eU + /* 64 */ , 0xbc1d7b41U, 0xbf9e10b3U, 0x4b6d40a0U, 0x48ee2b52U, 0xa38ae186U, 0xa0098a74U, 0x54fada67U, 0x5779b195U + /* 72 */ , 0x7345a2cbU, 0x70c6c939U, 0x8435992aU, 0x87b6f2d8U, 0x6cd2380cU, 0x6f5153feU, 0x9ba203edU, 0x9821681fU + /* 80 */ , 0xd3da2551U, 0xd0594ea3U, 0x24aa1eb0U, 0x27297542U, 0xcc4dbf96U, 0xcfced464U, 0x3b3d8477U, 0x38beef85U + /* 88 */ , 0x1c82fcdbU, 0x1f019729U, 0xebf2c73aU, 0xe871acc8U, 0x0315661cU, 0x00960deeU, 0xf4655dfdU, 0xf7e6360fU + /* 96 */ , 0x6293c661U, 0x6110ad93U, 0x95e3fd80U, 0x96609672U, 0x7d045ca6U, 0x7e873754U, 0x8a746747U, 0x89f70cb5U + /* 104 */ , 0xadcb1febU, 0xae487419U, 0x5abb240aU, 0x59384ff8U, 0xb25c852cU, 0xb1dfeedeU, 0x452cbecdU, 0x46afd53fU + /* 112 */ , 0x0d549871U, 0x0ed7f383U, 0xfa24a390U, 0xf9a7c862U, 0x12c302b6U, 0x11406944U, 0xe5b33957U, 0xe63052a5U + /* 120 */ , 0xc20c41fbU, 0xc18f2a09U, 0x357c7a1aU, 0x36ff11e8U, 0xdd9bdb3cU, 0xde18b0ceU, 0x2aebe0ddU, 0x29688b2fU + /* 128 */ , 0x783bf682U, 0x7bb89d70U, 0x8f4bcd63U, 0x8cc8a691U, 0x67ac6c45U, 0x642f07b7U, 0x90dc57a4U, 0x935f3c56U + /* 136 */ , 0xb7632f08U, 0xb4e044faU, 0x401314e9U, 0x43907f1bU, 0xa8f4b5cfU, 0xab77de3dU, 0x5f848e2eU, 0x5c07e5dcU + /* 144 */ , 0x17fca892U, 0x147fc360U, 0xe08c9373U, 0xe30ff881U, 0x086b3255U, 0x0be859a7U, 0xff1b09b4U, 0xfc986246U + /* 152 */ , 0xd8a47118U, 0xdb271aeaU, 0x2fd44af9U, 0x2c57210bU, 0xc733ebdfU, 0xc4b0802dU, 0x3043d03eU, 0x33c0bbccU + /* 160 */ , 0xa6b54ba2U, 0xa5362050U, 0x51c57043U, 0x52461bb1U, 0xb922d165U, 0xbaa1ba97U, 0x4e52ea84U, 0x4dd18176U + /* 168 */ , 0x69ed9228U, 0x6a6ef9daU, 0x9e9da9c9U, 0x9d1ec23bU, 0x767a08efU, 0x75f9631dU, 0x810a330eU, 0x828958fcU + /* 176 */ , 0xc97215b2U, 0xcaf17e40U, 0x3e022e53U, 0x3d8145a1U, 0xd6e58f75U, 0xd566e487U, 0x2195b494U, 0x2216df66U + /* 184 */ , 0x062acc38U, 0x05a9a7caU, 0xf15af7d9U, 0xf2d99c2bU, 0x19bd56ffU, 0x1a3e3d0dU, 0xeecd6d1eU, 0xed4e06ecU + /* 192 */ , 0xc4268dc3U, 0xc7a5e631U, 0x3356b622U, 0x30d5ddd0U, 0xdbb11704U, 0xd8327cf6U, 0x2cc12ce5U, 0x2f424717U + /* 200 */ , 0x0b7e5449U, 0x08fd3fbbU, 0xfc0e6fa8U, 0xff8d045aU, 0x14e9ce8eU, 0x176aa57cU, 0xe399f56fU, 0xe01a9e9dU + /* 208 */ , 0xabe1d3d3U, 0xa862b821U, 0x5c91e832U, 0x5f1283c0U, 0xb4764914U, 0xb7f522e6U, 0x430672f5U, 0x40851907U + /* 216 */ , 0x64b90a59U, 0x673a61abU, 0x93c931b8U, 0x904a5a4aU, 0x7b2e909eU, 0x78adfb6cU, 0x8c5eab7fU, 0x8fddc08dU + /* 224 */ , 0x1aa830e3U, 0x192b5b11U, 0xedd80b02U, 0xee5b60f0U, 0x053faa24U, 0x06bcc1d6U, 0xf24f91c5U, 0xf1ccfa37U + /* 232 */ , 0xd5f0e969U, 0xd673829bU, 0x2280d288U, 0x2103b97aU, 0xca6773aeU, 0xc9e4185cU, 0x3d17484fU, 0x3e9423bdU + /* 240 */ , 0x756f6ef3U, 0x76ec0501U, 0x821f5512U, 0x819c3ee0U, 0x6af8f434U, 0x697b9fc6U, 0x9d88cfd5U, 0x9e0ba427U + /* 248 */ , 0xba37b779U, 0xb9b4dc8bU, 0x4d478c98U, 0x4ec4e76aU, 0xa5a02dbeU, 0xa623464cU, 0x52d0165fU, 0x51537dadU + } + , + /* CRC32C table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7798a213U, 0xee304527U, 0x99a8e734U, 0xdc618a4eU, 0xabf9285dU, 0x3251cf69U, 0x45c96d7aU + /* 8 */ , 0xb8c3149dU, 0xcf5bb68eU, 0x56f351baU, 0x216bf3a9U, 0x64a29ed3U, 0x133a3cc0U, 0x8a92dbf4U, 0xfd0a79e7U + /* 16 */ , 0x81f1c53fU, 0xf669672cU, 0x6fc18018U, 0x1859220bU, 0x5d904f71U, 0x2a08ed62U, 0xb3a00a56U, 0xc438a845U + /* 24 */ , 0x3932d1a2U, 0x4eaa73b1U, 0xd7029485U, 0xa09a3696U, 0xe5535becU, 0x92cbf9ffU, 0x0b631ecbU, 0x7cfbbcd8U + /* 32 */ , 0x02e38b7fU, 0x757b296cU, 0xecd3ce58U, 0x9b4b6c4bU, 0xde820131U, 0xa91aa322U, 0x30b24416U, 0x472ae605U + /* 40 */ , 0xba209fe2U, 0xcdb83df1U, 0x5410dac5U, 0x238878d6U, 0x664115acU, 0x11d9b7bfU, 0x8871508bU, 0xffe9f298U + /* 48 */ , 0x83124e40U, 0xf48aec53U, 0x6d220b67U, 0x1abaa974U, 0x5f73c40eU, 0x28eb661dU, 0xb1438129U, 0xc6db233aU + /* 56 */ , 0x3bd15addU, 0x4c49f8ceU, 0xd5e11ffaU, 0xa279bde9U, 0xe7b0d093U, 0x90287280U, 0x098095b4U, 0x7e1837a7U + /* 64 */ , 0x04c617ffU, 0x735eb5ecU, 0xeaf652d8U, 0x9d6ef0cbU, 0xd8a79db1U, 0xaf3f3fa2U, 0x3697d896U, 0x410f7a85U + /* 72 */ , 0xbc050362U, 0xcb9da171U, 0x52354645U, 0x25ade456U, 0x6064892cU, 0x17fc2b3fU, 0x8e54cc0bU, 0xf9cc6e18U + /* 80 */ , 0x8537d2c0U, 0xf2af70d3U, 0x6b0797e7U, 0x1c9f35f4U, 0x5956588eU, 0x2ecefa9dU, 0xb7661da9U, 0xc0febfbaU + /* 88 */ , 0x3df4c65dU, 0x4a6c644eU, 0xd3c4837aU, 0xa45c2169U, 0xe1954c13U, 0x960dee00U, 0x0fa50934U, 0x783dab27U + /* 96 */ , 0x06259c80U, 0x71bd3e93U, 0xe815d9a7U, 0x9f8d7bb4U, 0xda4416ceU, 0xaddcb4ddU, 0x347453e9U, 0x43ecf1faU + /* 104 */ , 0xbee6881dU, 0xc97e2a0eU, 0x50d6cd3aU, 0x274e6f29U, 0x62870253U, 0x151fa040U, 0x8cb74774U, 0xfb2fe567U + /* 112 */ , 0x87d459bfU, 0xf04cfbacU, 0x69e41c98U, 0x1e7cbe8bU, 0x5bb5d3f1U, 0x2c2d71e2U, 0xb58596d6U, 0xc21d34c5U + /* 120 */ , 0x3f174d22U, 0x488fef31U, 0xd1270805U, 0xa6bfaa16U, 0xe376c76cU, 0x94ee657fU, 0x0d46824bU, 0x7ade2058U + /* 128 */ , 0xf9fac3fbU, 0x8e6261e8U, 0x17ca86dcU, 0x605224cfU, 0x259b49b5U, 0x5203eba6U, 0xcbab0c92U, 0xbc33ae81U + /* 136 */ , 0x4139d766U, 0x36a17575U, 0xaf099241U, 0xd8913052U, 0x9d585d28U, 0xeac0ff3bU, 0x7368180fU, 0x04f0ba1cU + /* 144 */ , 0x780b06c4U, 0x0f93a4d7U, 0x963b43e3U, 0xe1a3e1f0U, 0xa46a8c8aU, 0xd3f22e99U, 0x4a5ac9adU, 0x3dc26bbeU + /* 152 */ , 0xc0c81259U, 0xb750b04aU, 0x2ef8577eU, 0x5960f56dU, 0x1ca99817U, 0x6b313a04U, 0xf299dd30U, 0x85017f23U + /* 160 */ , 0xfb194884U, 0x8c81ea97U, 0x15290da3U, 0x62b1afb0U, 0x2778c2caU, 0x50e060d9U, 0xc94887edU, 0xbed025feU + /* 168 */ , 0x43da5c19U, 0x3442fe0aU, 0xadea193eU, 0xda72bb2dU, 0x9fbbd657U, 0xe8237444U, 0x718b9370U, 0x06133163U + /* 176 */ , 0x7ae88dbbU, 0x0d702fa8U, 0x94d8c89cU, 0xe3406a8fU, 0xa68907f5U, 0xd111a5e6U, 0x48b942d2U, 0x3f21e0c1U + /* 184 */ , 0xc22b9926U, 0xb5b33b35U, 0x2c1bdc01U, 0x5b837e12U, 0x1e4a1368U, 0x69d2b17bU, 0xf07a564fU, 0x87e2f45cU + /* 192 */ , 0xfd3cd404U, 0x8aa47617U, 0x130c9123U, 0x64943330U, 0x215d5e4aU, 0x56c5fc59U, 0xcf6d1b6dU, 0xb8f5b97eU + /* 200 */ , 0x45ffc099U, 0x3267628aU, 0xabcf85beU, 0xdc5727adU, 0x999e4ad7U, 0xee06e8c4U, 0x77ae0ff0U, 0x0036ade3U + /* 208 */ , 0x7ccd113bU, 0x0b55b328U, 0x92fd541cU, 0xe565f60fU, 0xa0ac9b75U, 0xd7343966U, 0x4e9cde52U, 0x39047c41U + /* 216 */ , 0xc40e05a6U, 0xb396a7b5U, 0x2a3e4081U, 0x5da6e292U, 0x186f8fe8U, 0x6ff72dfbU, 0xf65fcacfU, 0x81c768dcU + /* 224 */ , 0xffdf5f7bU, 0x8847fd68U, 0x11ef1a5cU, 0x6677b84fU, 0x23bed535U, 0x54267726U, 0xcd8e9012U, 0xba163201U + /* 232 */ , 0x471c4be6U, 0x3084e9f5U, 0xa92c0ec1U, 0xdeb4acd2U, 0x9b7dc1a8U, 0xece563bbU, 0x754d848fU, 0x02d5269cU + /* 240 */ , 0x7e2e9a44U, 0x09b63857U, 0x901edf63U, 0xe7867d70U, 0xa24f100aU, 0xd5d7b219U, 0x4c7f552dU, 0x3be7f73eU + /* 248 */ , 0xc6ed8ed9U, 0xb1752ccaU, 0x28ddcbfeU, 0x5f4569edU, 0x1a8c0497U, 0x6d14a684U, 0xf4bc41b0U, 0x8324e3a3U + } + , + /* CRC32C table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7e9241a5U, 0x0d526f4fU, 0x73c02eeaU, 0x1aa4de9eU, 0x64369f3bU, 0x17f6b1d1U, 0x6964f074U + /* 8 */ , 0xc53e5138U, 0xbbac109dU, 0xc86c3e77U, 0xb6fe7fd2U, 0xdf9a8fa6U, 0xa108ce03U, 0xd2c8e0e9U, 0xac5aa14cU + /* 16 */ , 0x8a7da270U, 0xf4efe3d5U, 0x872fcd3fU, 0xf9bd8c9aU, 0x90d97ceeU, 0xee4b3d4bU, 0x9d8b13a1U, 0xe3195204U + /* 24 */ , 0x4f43f348U, 0x31d1b2edU, 0x42119c07U, 0x3c83dda2U, 0x55e72dd6U, 0x2b756c73U, 0x58b54299U, 0x2627033cU + /* 32 */ , 0x14fb44e1U, 0x6a690544U, 0x19a92baeU, 0x673b6a0bU, 0x0e5f9a7fU, 0x70cddbdaU, 0x030df530U, 0x7d9fb495U + /* 40 */ , 0xd1c515d9U, 0xaf57547cU, 0xdc977a96U, 0xa2053b33U, 0xcb61cb47U, 0xb5f38ae2U, 0xc633a408U, 0xb8a1e5adU + /* 48 */ , 0x9e86e691U, 0xe014a734U, 0x93d489deU, 0xed46c87bU, 0x8422380fU, 0xfab079aaU, 0x89705740U, 0xf7e216e5U + /* 56 */ , 0x5bb8b7a9U, 0x252af60cU, 0x56ead8e6U, 0x28789943U, 0x411c6937U, 0x3f8e2892U, 0x4c4e0678U, 0x32dc47ddU + /* 64 */ , 0xd98065c7U, 0xa7122462U, 0xd4d20a88U, 0xaa404b2dU, 0xc324bb59U, 0xbdb6fafcU, 0xce76d416U, 0xb0e495b3U + /* 72 */ , 0x1cbe34ffU, 0x622c755aU, 0x11ec5bb0U, 0x6f7e1a15U, 0x061aea61U, 0x7888abc4U, 0x0b48852eU, 0x75dac48bU + /* 80 */ , 0x53fdc7b7U, 0x2d6f8612U, 0x5eafa8f8U, 0x203de95dU, 0x49591929U, 0x37cb588cU, 0x440b7666U, 0x3a9937c3U + /* 88 */ , 0x96c3968fU, 0xe851d72aU, 0x9b91f9c0U, 0xe503b865U, 0x8c674811U, 0xf2f509b4U, 0x8135275eU, 0xffa766fbU + /* 96 */ , 0xcd7b2126U, 0xb3e96083U, 0xc0294e69U, 0xbebb0fccU, 0xd7dfffb8U, 0xa94dbe1dU, 0xda8d90f7U, 0xa41fd152U + /* 104 */ , 0x0845701eU, 0x76d731bbU, 0x05171f51U, 0x7b855ef4U, 0x12e1ae80U, 0x6c73ef25U, 0x1fb3c1cfU, 0x6121806aU + /* 112 */ , 0x47068356U, 0x3994c2f3U, 0x4a54ec19U, 0x34c6adbcU, 0x5da25dc8U, 0x23301c6dU, 0x50f03287U, 0x2e627322U + /* 120 */ , 0x8238d26eU, 0xfcaa93cbU, 0x8f6abd21U, 0xf1f8fc84U, 0x989c0cf0U, 0xe60e4d55U, 0x95ce63bfU, 0xeb5c221aU + /* 128 */ , 0x4377278bU, 0x3de5662eU, 0x4e2548c4U, 0x30b70961U, 0x59d3f915U, 0x2741b8b0U, 0x5481965aU, 0x2a13d7ffU + /* 136 */ , 0x864976b3U, 0xf8db3716U, 0x8b1b19fcU, 0xf5895859U, 0x9ceda82dU, 0xe27fe988U, 0x91bfc762U, 0xef2d86c7U + /* 144 */ , 0xc90a85fbU, 0xb798c45eU, 0xc458eab4U, 0xbacaab11U, 0xd3ae5b65U, 0xad3c1ac0U, 0xdefc342aU, 0xa06e758fU + /* 152 */ , 0x0c34d4c3U, 0x72a69566U, 0x0166bb8cU, 0x7ff4fa29U, 0x16900a5dU, 0x68024bf8U, 0x1bc26512U, 0x655024b7U + /* 160 */ , 0x578c636aU, 0x291e22cfU, 0x5ade0c25U, 0x244c4d80U, 0x4d28bdf4U, 0x33bafc51U, 0x407ad2bbU, 0x3ee8931eU + /* 168 */ , 0x92b23252U, 0xec2073f7U, 0x9fe05d1dU, 0xe1721cb8U, 0x8816ecccU, 0xf684ad69U, 0x85448383U, 0xfbd6c226U + /* 176 */ , 0xddf1c11aU, 0xa36380bfU, 0xd0a3ae55U, 0xae31eff0U, 0xc7551f84U, 0xb9c75e21U, 0xca0770cbU, 0xb495316eU + /* 184 */ , 0x18cf9022U, 0x665dd187U, 0x159dff6dU, 0x6b0fbec8U, 0x026b4ebcU, 0x7cf90f19U, 0x0f3921f3U, 0x71ab6056U + /* 192 */ , 0x9af7424cU, 0xe46503e9U, 0x97a52d03U, 0xe9376ca6U, 0x80539cd2U, 0xfec1dd77U, 0x8d01f39dU, 0xf393b238U + /* 200 */ , 0x5fc91374U, 0x215b52d1U, 0x529b7c3bU, 0x2c093d9eU, 0x456dcdeaU, 0x3bff8c4fU, 0x483fa2a5U, 0x36ade300U + /* 208 */ , 0x108ae03cU, 0x6e18a199U, 0x1dd88f73U, 0x634aced6U, 0x0a2e3ea2U, 0x74bc7f07U, 0x077c51edU, 0x79ee1048U + /* 216 */ , 0xd5b4b104U, 0xab26f0a1U, 0xd8e6de4bU, 0xa6749feeU, 0xcf106f9aU, 0xb1822e3fU, 0xc24200d5U, 0xbcd04170U + /* 224 */ , 0x8e0c06adU, 0xf09e4708U, 0x835e69e2U, 0xfdcc2847U, 0x94a8d833U, 0xea3a9996U, 0x99fab77cU, 0xe768f6d9U + /* 232 */ , 0x4b325795U, 0x35a01630U, 0x466038daU, 0x38f2797fU, 0x5196890bU, 0x2f04c8aeU, 0x5cc4e644U, 0x2256a7e1U + /* 240 */ , 0x0471a4ddU, 0x7ae3e578U, 0x0923cb92U, 0x77b18a37U, 0x1ed57a43U, 0x60473be6U, 0x1387150cU, 0x6d1554a9U + /* 248 */ , 0xc14ff5e5U, 0xbfddb440U, 0xcc1d9aaaU, 0xb28fdb0fU, 0xdbeb2b7bU, 0xa5796adeU, 0xd6b94434U, 0xa82b0591U + } + , + /* CRC32C table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8aa45ddU, 0x812367bfU, 0x39892262U, 0xf331227bU, 0x4b9b67a6U, 0x721245c4U, 0xcab80019U + /* 8 */ , 0xe66344f6U, 0x5ec9012bU, 0x67402349U, 0xdfea6694U, 0x1552668dU, 0xadf82350U, 0x94710132U, 0x2cdb44efU + /* 16 */ , 0x3db164e9U, 0x851b2134U, 0xbc920356U, 0x0438468bU, 0xce804692U, 0x762a034fU, 0x4fa3212dU, 0xf70964f0U + /* 24 */ , 0xdbd2201fU, 0x637865c2U, 0x5af147a0U, 0xe25b027dU, 0x28e30264U, 0x904947b9U, 0xa9c065dbU, 0x116a2006U + /* 32 */ , 0x8b1425d7U, 0x33be600aU, 0x0a374268U, 0xb29d07b5U, 0x782507acU, 0xc08f4271U, 0xf9066013U, 0x41ac25ceU + /* 40 */ , 0x6d776121U, 0xd5dd24fcU, 0xec54069eU, 0x54fe4343U, 0x9e46435aU, 0x26ec0687U, 0x1f6524e5U, 0xa7cf6138U + /* 48 */ , 0xb6a5413eU, 0x0e0f04e3U, 0x37862681U, 0x8f2c635cU, 0x45946345U, 0xfd3e2698U, 0xc4b704faU, 0x7c1d4127U + /* 56 */ , 0x50c605c8U, 0xe86c4015U, 0xd1e56277U, 0x694f27aaU, 0xa3f727b3U, 0x1b5d626eU, 0x22d4400cU, 0x9a7e05d1U + /* 64 */ , 0xe75fa6abU, 0x5ff5e376U, 0x667cc114U, 0xded684c9U, 0x146e84d0U, 0xacc4c10dU, 0x954de36fU, 0x2de7a6b2U + /* 72 */ , 0x013ce25dU, 0xb996a780U, 0x801f85e2U, 0x38b5c03fU, 0xf20dc026U, 0x4aa785fbU, 0x732ea799U, 0xcb84e244U + /* 80 */ , 0xdaeec242U, 0x6244879fU, 0x5bcda5fdU, 0xe367e020U, 0x29dfe039U, 0x9175a5e4U, 0xa8fc8786U, 0x1056c25bU + /* 88 */ , 0x3c8d86b4U, 0x8427c369U, 0xbdaee10bU, 0x0504a4d6U, 0xcfbca4cfU, 0x7716e112U, 0x4e9fc370U, 0xf63586adU + /* 96 */ , 0x6c4b837cU, 0xd4e1c6a1U, 0xed68e4c3U, 0x55c2a11eU, 0x9f7aa107U, 0x27d0e4daU, 0x1e59c6b8U, 0xa6f38365U + /* 104 */ , 0x8a28c78aU, 0x32828257U, 0x0b0ba035U, 0xb3a1e5e8U, 0x7919e5f1U, 0xc1b3a02cU, 0xf83a824eU, 0x4090c793U + /* 112 */ , 0x51fae795U, 0xe950a248U, 0xd0d9802aU, 0x6873c5f7U, 0xa2cbc5eeU, 0x1a618033U, 0x23e8a251U, 0x9b42e78cU + /* 120 */ , 0xb799a363U, 0x0f33e6beU, 0x36bac4dcU, 0x8e108101U, 0x44a88118U, 0xfc02c4c5U, 0xc58be6a7U, 0x7d21a37aU + /* 128 */ , 0x3fc9a052U, 0x8763e58fU, 0xbeeac7edU, 0x06408230U, 0xccf88229U, 0x7452c7f4U, 0x4ddbe596U, 0xf571a04bU + /* 136 */ , 0xd9aae4a4U, 0x6100a179U, 0x5889831bU, 0xe023c6c6U, 0x2a9bc6dfU, 0x92318302U, 0xabb8a160U, 0x1312e4bdU + /* 144 */ , 0x0278c4bbU, 0xbad28166U, 0x835ba304U, 0x3bf1e6d9U, 0xf149e6c0U, 0x49e3a31dU, 0x706a817fU, 0xc8c0c4a2U + /* 152 */ , 0xe41b804dU, 0x5cb1c590U, 0x6538e7f2U, 0xdd92a22fU, 0x172aa236U, 0xaf80e7ebU, 0x9609c589U, 0x2ea38054U + /* 160 */ , 0xb4dd8585U, 0x0c77c058U, 0x35fee23aU, 0x8d54a7e7U, 0x47eca7feU, 0xff46e223U, 0xc6cfc041U, 0x7e65859cU + /* 168 */ , 0x52bec173U, 0xea1484aeU, 0xd39da6ccU, 0x6b37e311U, 0xa18fe308U, 0x1925a6d5U, 0x20ac84b7U, 0x9806c16aU + /* 176 */ , 0x896ce16cU, 0x31c6a4b1U, 0x084f86d3U, 0xb0e5c30eU, 0x7a5dc317U, 0xc2f786caU, 0xfb7ea4a8U, 0x43d4e175U + /* 184 */ , 0x6f0fa59aU, 0xd7a5e047U, 0xee2cc225U, 0x568687f8U, 0x9c3e87e1U, 0x2494c23cU, 0x1d1de05eU, 0xa5b7a583U + /* 192 */ , 0xd89606f9U, 0x603c4324U, 0x59b56146U, 0xe11f249bU, 0x2ba72482U, 0x930d615fU, 0xaa84433dU, 0x122e06e0U + /* 200 */ , 0x3ef5420fU, 0x865f07d2U, 0xbfd625b0U, 0x077c606dU, 0xcdc46074U, 0x756e25a9U, 0x4ce707cbU, 0xf44d4216U + /* 208 */ , 0xe5276210U, 0x5d8d27cdU, 0x640405afU, 0xdcae4072U, 0x1616406bU, 0xaebc05b6U, 0x973527d4U, 0x2f9f6209U + /* 216 */ , 0x034426e6U, 0xbbee633bU, 0x82674159U, 0x3acd0484U, 0xf075049dU, 0x48df4140U, 0x71566322U, 0xc9fc26ffU + /* 224 */ , 0x5382232eU, 0xeb2866f3U, 0xd2a14491U, 0x6a0b014cU, 0xa0b30155U, 0x18194488U, 0x219066eaU, 0x993a2337U + /* 232 */ , 0xb5e167d8U, 0x0d4b2205U, 0x34c20067U, 0x8c6845baU, 0x46d045a3U, 0xfe7a007eU, 0xc7f3221cU, 0x7f5967c1U + /* 240 */ , 0x6e3347c7U, 0xd699021aU, 0xef102078U, 0x57ba65a5U, 0x9d0265bcU, 0x25a82061U, 0x1c210203U, 0xa48b47deU + /* 248 */ , 0x88500331U, 0x30fa46ecU, 0x0973648eU, 0xb1d92153U, 0x7b61214aU, 0xc3cb6497U, 0xfa4246f5U, 0x42e80328U + } + #endif + }; diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp index 5bb64303b6b..b2509b23094 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,12 +68,11 @@ class zarch { }; private: - static address _handler_for_unsafe_access_entry; - static int _atomic_memory_operation_lock; static address _partial_subtype_check; static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; + static juint _crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. static address _trot_table_addr; @@ -91,11 +90,11 @@ class zarch { static int atomic_memory_operation_lock() { return _atomic_memory_operation_lock; } static void set_atomic_memory_operation_lock(int value) { _atomic_memory_operation_lock = value; } - static address handler_for_unsafe_access_entry() { return _handler_for_unsafe_access_entry; } - static address partial_subtype_check() { return _partial_subtype_check; } + static void generate_load_absolute_address(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents); static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); + static void generate_load_crc32c_table_addr(MacroAssembler* masm, Register table); // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. static void generate_load_trot_table_addr(MacroAssembler* masm, Register table); diff --git a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp index 20a9a3e9571..56a76871738 100644 --- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2017 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -642,13 +642,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -// Unused, should never pass by. -address TemplateInterpreterGenerator::generate_continuation_for (TosState state) { - address entry = __ pc(); - __ should_not_reach_here(); - return entry; -} - address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -683,6 +676,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, __ z_llgc(size, Address(cache, offset, flags_offset+(sizeof(size_t)-1))); __ z_sllg(size, size, Interpreter::logStackElementSize); // Each argument size in bytes. __ z_agr(Z_esp, size); // Pop arguments. + + __ check_and_handle_popframe(Z_thread); + __ check_and_handle_earlyret(Z_thread); + __ dispatch_next(state, step); BLOCK_COMMENT("} return_entry"); @@ -1186,11 +1183,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // native_call: assert that mdo == NULL const bool check_for_mdo = !native_call DEBUG_ONLY(|| native_call); if (ProfileInterpreter && check_for_mdo) { -#ifdef FAST_DISPATCH - // FAST_DISPATCH and ProfileInterpreter are mutually exclusive since - // they both use I2. - assert(0, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive"); -#endif // FAST_DISPATCH Label get_continue; __ load_and_test_long(Rmdp, method_(method_data)); @@ -1933,8 +1925,11 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { return entry_point; } -// Method entry for static native methods: -// int java.util.zip.CRC32.update(int crc, int b) + +/** + * Method entry for static native methods: + * int java.util.zip.CRC32.update(int crc, int b) + */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { if (UseCRC32Intrinsics) { @@ -1964,7 +1959,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { __ z_llgf(crc, 2 * wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1); + __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1, true); // Restore caller sp for c2i case. __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. @@ -1983,9 +1978,11 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { } -// Method entry for static native methods: -// int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len) -// int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) +/** + * Method entry for static native methods: + * int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len) + * int java.util.zip.CRC32.updateByteBuffer(int crc, long* buf, int off, int len) + */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { if (UseCRC32Intrinsics) { @@ -2020,10 +2017,10 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // data = buf + off BLOCK_COMMENT("CRC32_updateByteBuffer {"); __ z_llgf(crc, 5*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process - } else { // Used for "updateBytes update". + } else { // Used for "updateBytes update". // crc @ (SP + 4W) (32bit) // buf @ (SP + 3W) (64bit ptr to byte array) // off @ (SP + 2W) (32bit) @@ -2031,7 +2028,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // data = buf + off + base_offset BLOCK_COMMENT("CRC32_updateBytes {"); __ z_llgf(crc, 4*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); @@ -2041,7 +2038,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, true); __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. // Restore caller sp for c2i case. @@ -2060,8 +2057,79 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI return NULL; } -// Not supported + +/** + * Method entry for intrinsic-candidate (non-native) methods: + * int java.util.zip.CRC32C.updateBytes( int crc, byte[] b, int off, int end) + * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long* buf, int off, int end) + * Unlike CRC32, CRC32C does not have any methods marked as native + * CRC32C also uses an "end" variable instead of the length variable CRC32 uses + */ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + + if (UseCRC32CIntrinsics) { + uint64_t entry_off = __ offset(); + + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. + + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = Z_esp; + const Register crc = Z_ARG1; // crc value + const Register data = Z_ARG2; // address of java byte array + const Register dataLen = Z_ARG3; // source data len + const Register table = Z_ARG4; // address of crc32 table + const Register t0 = Z_R10; // work reg for kernel* emitters + const Register t1 = Z_R11; // work reg for kernel* emitters + const Register t2 = Z_R12; // work reg for kernel* emitters + const Register t3 = Z_R13; // work reg for kernel* emitters + + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateByteBuffer direct". + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + __ z_llgf(crc, 5*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as + __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) + } else { // Used for "updateBytes update". + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + BLOCK_COMMENT("CRC32C_updateBytes {"); + __ z_llgf(crc, 4*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as + __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) + __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); + } + + StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); + + __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. + __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, false); + __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. + + // Restore caller sp for c2i case. + __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. + + __ z_br(Z_R14); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return __ addr_at(entry_off); + } + return NULL; } diff --git a/hotspot/src/cpu/s390/vm/templateTable_s390.cpp b/hotspot/src/cpu/s390/vm/templateTable_s390.cpp index 83d707dbd60..becbb0e48b5 100644 --- a/hotspot/src/cpu/s390/vm/templateTable_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateTable_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3466,7 +3466,7 @@ void TemplateTable::invokevirtual_helper(Register index, __ z_sllg(index, index, exact_log2(vtableEntry::size_in_bytes())); __ mem2reg_opt(method, Address(Z_tmp_2, index, - InstanceKlass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes()))); + Klass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes()))); __ profile_arguments_type(Z_ARG4, method, Z_ARG5, true); __ jump_from_interpreted(method, Z_ARG4); BLOCK_COMMENT("} invokevirtual_helper"); @@ -3708,7 +3708,7 @@ void TemplateTable::_new() { __ z_sllg(offset, offset, LogBytesPerWord); // Convert to to offset. // Get InstanceKlass. Register iklass = cpool; - __ z_lg(iklass, Address(cpool, offset, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(cpool, offset, iklass); // Make sure klass is initialized & doesn't have finalizer. // Make sure klass is fully initialized. @@ -3895,7 +3895,7 @@ void TemplateTable::checkcast() { __ z_lgr(Z_ARG4, Z_tos); // Save receiver. __ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing - __ mem2reg_opt(klass, Address(cpool, index, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(cpool, index, klass); __ bind(resolved); @@ -3969,8 +3969,7 @@ void TemplateTable::instanceof() { __ load_klass(subklass, Z_tos); __ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing - __ mem2reg_opt(klass, - Address(cpool, index, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(cpool, index, klass); __ bind(resolved); diff --git a/hotspot/src/cpu/s390/vm/vm_version_s390.cpp b/hotspot/src/cpu/s390/vm/vm_version_s390.cpp index 55dbd30aec8..6350c0b9b8f 100644 --- a/hotspot/src/cpu/s390/vm/vm_version_s390.cpp +++ b/hotspot/src/cpu/s390/vm/vm_version_s390.cpp @@ -111,13 +111,23 @@ void VM_Version::initialize() { ContendedPaddingWidth = cache_line_size; } - // On z/Architecture, the CRC32 intrinsics had to be implemented "by hand". - // They cannot be based on the CHECKSUM instruction which has been there - // since the very beginning (of z/Architecture). It computes "some kind of" a checksum - // which has nothing to do with the CRC32 algorithm. + // On z/Architecture, the CRC32/CRC32C intrinsics are implemented "by hand". + // TODO: Provide implementation based on the vector instructions available from z13. + // Note: The CHECKSUM instruction, which has been there since the very beginning + // (of z/Architecture), computes "some kind of" a checksum. + // It has nothing to do with the CRC32 algorithm. if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + + // TODO: Provide implementation. + if (UseAdler32Intrinsics) { + warning("Adler32Intrinsics not available on this CPU."); + FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); + } // On z/Architecture, we take UseAES as the general switch to enable/disable the AES intrinsics. // The specific, and yet to be defined, switches UseAESxxxIntrinsics will then be set @@ -195,11 +205,6 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } - if (UseAdler32Intrinsics) { - warning("Adler32Intrinsics not available on this CPU."); - FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); - } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); } diff --git a/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp b/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp index c2c3ab246b8..de0a351ea04 100644 --- a/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp +++ b/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp @@ -83,7 +83,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { __ load_klass(rcvr_klass, Z_ARG1); // Set method (in case of interpreted method), and destination address. - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + + int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index * vtableEntry::size_in_bytes(); #ifndef PRODUCT @@ -96,8 +96,8 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // worst case actual size padding_bytes += __ load_const_size() - __ load_const_optimized_rtn_len(vtable_idx, vtable_index*vtableEntry::size_in_bytes(), true); - assert(Immediate::is_uimm12(in_bytes(InstanceKlass::vtable_length_offset())), "disp to large"); - __ z_cl(vtable_idx, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); + assert(Immediate::is_uimm12(in_bytes(Klass::vtable_length_offset())), "disp to large"); + __ z_cl(vtable_idx, in_bytes(Klass::vtable_length_offset()), rcvr_klass); __ z_brl(L); __ z_lghi(Z_ARG3, vtable_index); // Debug code, don't optimize. __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), Z_ARG1, Z_ARG3, false); @@ -187,11 +187,11 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { __ load_klass(rcvr_klass, Z_ARG1); // Load start of itable entries into itable_entry. - __ z_llgf(vtable_len, Address(rcvr_klass, InstanceKlass::vtable_length_offset())); + __ z_llgf(vtable_len, Address(rcvr_klass, Klass::vtable_length_offset())); __ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); // Loop over all itable entries until desired interfaceOop(Rinterface) found. - const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); + const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); // Count unused bytes. start_pc = __ pc(); __ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len); diff --git a/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp index f9ba7983fd2..8ff2bec1dfc 100644 --- a/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -270,9 +270,7 @@ void AbstractInterpreter::layout_activation(Method* method, assert(locals < interpreter_frame->sp() || locals > (interpreter_frame->sp() + 16), "locals in save area"); assert(locals < interpreter_frame->fp() || locals >= (interpreter_frame->fp() + 16), "locals in save area"); } -#ifdef _LP64 assert(*interpreter_frame->register_addr(I5_savedSP) & 1, "must be odd"); -#endif *interpreter_frame->register_addr(Lmethod) = (intptr_t) method; *interpreter_frame->register_addr(Llocals) = (intptr_t) locals; @@ -283,9 +281,6 @@ void AbstractInterpreter::layout_activation(Method* method, *interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache(); // save the mirror in the interpreter frame *interpreter_frame->interpreter_frame_mirror_addr() = method->method_holder()->java_mirror(); -#ifdef FAST_DISPATCH - *interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table(); -#endif #ifdef ASSERT BasicObjectLock* mp = (BasicObjectLock*)monitors; diff --git a/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp b/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp index 67d4307ff74..0ce1f5fac48 100644 --- a/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp @@ -34,10 +34,6 @@ class Bytes: AllStatic { // can I count on address always being a pointer to an unsigned char? Yes - // Returns true, if the byte ordering used by Java is different from the nativ byte ordering - // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. - static inline bool is_Java_byte_ordering_different() { return false; } - // Thus, a swap between native and Java ordering is always a no-op: static inline u2 swap_u2(u2 x) { return x; } static inline u4 swap_u4(u4 x) { return x; } diff --git a/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp index 8c3a19a9e78..abaf500ebd7 100644 --- a/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -22,10 +22,4 @@ * */ -#include "precompiled.hpp" -#include "c1/c1_FpuStackSim.hpp" -#include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" -#include "utilities/ostream.hpp" - // No FPU stack on SPARC diff --git a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp index ae4262bb73b..71e6276f09c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -159,21 +159,12 @@ public: -#ifdef _LP64 static LIR_Opr as_long_opr(Register r) { return as_long_single_opr(r); } static LIR_Opr as_pointer_opr(Register r) { return as_long_single_opr(r); } -#else - static LIR_Opr as_long_opr(Register r) { - return as_long_pair_opr(r); - } - static LIR_Opr as_pointer_opr(Register r) { - return as_opr(r); - } -#endif static LIR_Opr as_float_opr(FloatRegister r) { return LIR_OprFact::single_fpu(r->encoding()); } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index ae2942f19b5..e56618dac87 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -556,11 +556,9 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { // guarantee that 32-bit loads always sign extended but that isn't // true and since sign extension isn't free, it would impose a // slight cost. -#ifdef _LP64 if (op->type() == T_INT) { __ br(acond, false, Assembler::pn, *(op->label())); } else -#endif __ brx(acond, false, Assembler::pn, *(op->label())); } // The peephole pass fills the delay slot @@ -576,12 +574,7 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { Register rlo = dst->as_register_lo(); Register rhi = dst->as_register_hi(); Register rval = op->in_opr()->as_register(); -#ifdef _LP64 __ sra(rval, 0, rlo); -#else - __ mov(rval, rlo); - __ sra(rval, BitsPerInt-1, rhi); -#endif break; } case Bytecodes::_i2d: @@ -614,11 +607,7 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { Register rlo = op->in_opr()->as_register_lo(); Register rhi = op->in_opr()->as_register_hi(); Register rdst = dst->as_register(); -#ifdef _LP64 __ sra(rlo, 0, rdst); -#else - __ mov(rlo, rdst); -#endif break; } case Bytecodes::_d2f: @@ -711,7 +700,6 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType case T_SHORT : __ sth(from_reg->as_register(), base, offset); break; case T_INT : __ stw(from_reg->as_register(), base, offset); break; case T_LONG : -#ifdef _LP64 if (unaligned || PatchALot) { // Don't use O7 here because it may be equal to 'base' (see LIR_Assembler::reg2mem) assert(G3_scratch != base, "can't handle this"); @@ -722,11 +710,6 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType } else { __ stx(from_reg->as_register_lo(), base, offset); } -#else - assert(Assembler::is_simm13(offset + 4), "must be"); - __ stw(from_reg->as_register_lo(), base, offset + lo_word_offset_in_bytes); - __ stw(from_reg->as_register_hi(), base, offset + hi_word_offset_in_bytes); -#endif break; case T_ADDRESS: case T_METADATA: @@ -778,12 +761,7 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicTy case T_SHORT : __ sth(from_reg->as_register(), base, disp); break; case T_INT : __ stw(from_reg->as_register(), base, disp); break; case T_LONG : -#ifdef _LP64 __ stx(from_reg->as_register_lo(), base, disp); -#else - assert(from_reg->as_register_hi()->successor() == from_reg->as_register_lo(), "must match"); - __ std(from_reg->as_register_hi(), base, disp); -#endif break; case T_ADDRESS: __ st_ptr(from_reg->as_register(), base, disp); @@ -826,40 +804,22 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ case T_INT : __ ld(base, offset, to_reg->as_register()); break; case T_LONG : if (!unaligned && !PatchALot) { -#ifdef _LP64 __ ldx(base, offset, to_reg->as_register_lo()); -#else - assert(to_reg->as_register_hi()->successor() == to_reg->as_register_lo(), - "must be sequential"); - __ ldd(base, offset, to_reg->as_register_hi()); -#endif } else { -#ifdef _LP64 assert(base != to_reg->as_register_lo(), "can't handle this"); assert(O7 != to_reg->as_register_lo(), "can't handle this"); __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_lo()); __ lduw(base, offset + lo_word_offset_in_bytes, O7); // in case O7 is base or offset, use it last __ sllx(to_reg->as_register_lo(), 32, to_reg->as_register_lo()); __ or3(to_reg->as_register_lo(), O7, to_reg->as_register_lo()); -#else - if (base == to_reg->as_register_lo()) { - __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_hi()); - __ ld(base, offset + lo_word_offset_in_bytes, to_reg->as_register_lo()); - } else { - __ ld(base, offset + lo_word_offset_in_bytes, to_reg->as_register_lo()); - __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_hi()); - } -#endif } break; case T_METADATA: __ ld_ptr(base, offset, to_reg->as_register()); break; case T_ADDRESS: -#ifdef _LP64 if (offset == oopDesc::klass_offset_in_bytes() && UseCompressedClassPointers) { __ lduw(base, offset, to_reg->as_register()); __ decode_klass_not_null(to_reg->as_register()); } else -#endif { __ ld_ptr(base, offset, to_reg->as_register()); } @@ -921,13 +881,7 @@ int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, disp, to_reg->as_float_reg()); break; case T_DOUBLE: __ ldf(FloatRegisterImpl::D, base, disp, to_reg->as_double_reg()); break; case T_LONG : -#ifdef _LP64 __ ldx(base, disp, to_reg->as_register_lo()); -#else - assert(to_reg->as_register_hi()->successor() == to_reg->as_register_lo(), - "must be sequential"); - __ ldd(base, disp, to_reg->as_register_hi()); -#endif break; default : ShouldNotReachHere(); } @@ -1107,16 +1061,9 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod jlong con = c->as_jlong(); if (to_reg->is_double_cpu()) { -#ifdef _LP64 __ set(con, to_reg->as_register_lo()); -#else - __ set(low(con), to_reg->as_register_lo()); - __ set(high(con), to_reg->as_register_hi()); -#endif -#ifdef _LP64 } else if (to_reg->is_single_cpu()) { __ set(con, to_reg->as_register()); -#endif } else { ShouldNotReachHere(); assert(to_reg->is_double_fpu(), "wrong register kind"); @@ -1190,12 +1137,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod __ ldf (FloatRegisterImpl::D, O7, const_addrlit.low10(), to_reg->as_double_reg()); } else { assert(to_reg->is_double_cpu(), "Must be a long register."); -#ifdef _LP64 __ set(jlong_cast(c->as_jdouble()), to_reg->as_register_lo()); -#else - __ set(low(jlong_cast(c->as_jdouble())), to_reg->as_register_lo()); - __ set(high(jlong_cast(c->as_jdouble())), to_reg->as_register_hi()); -#endif } } @@ -1366,22 +1308,10 @@ void LIR_Assembler::reg2reg(LIR_Opr from_reg, LIR_Opr to_reg) { } } else if (!from_reg->is_float_kind() && !to_reg->is_float_kind()) { if (from_reg->is_double_cpu()) { -#ifdef _LP64 __ mov(from_reg->as_pointer_register(), to_reg->as_pointer_register()); -#else - assert(to_reg->is_double_cpu() && - from_reg->as_register_hi() != to_reg->as_register_lo() && - from_reg->as_register_lo() != to_reg->as_register_hi(), - "should both be long and not overlap"); - // long to long moves - __ mov(from_reg->as_register_hi(), to_reg->as_register_hi()); - __ mov(from_reg->as_register_lo(), to_reg->as_register_lo()); -#endif -#ifdef _LP64 } else if (to_reg->is_double_cpu()) { // int to int moves __ mov(from_reg->as_register(), to_reg->as_register_lo()); -#endif } else { // int to int moves __ mov(from_reg->as_register(), to_reg->as_register()); @@ -1460,21 +1390,6 @@ void LIR_Assembler::return_op(LIR_Opr result) { if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) { __ reserved_stack_check(); } - // the poll may need a register so just pick one that isn't the return register -#if defined(TIERED) && !defined(_LP64) - if (result->type_field() == LIR_OprDesc::long_type) { - // Must move the result to G1 - // Must leave proper result in O0,O1 and G1 (TIERED only) - __ sllx(I0, 32, G1); // Shift bits into high G1 - __ srl (I1, 0, I1); // Zero extend O1 (harmless?) - __ or3 (I1, G1, G1); // OR 64 bits into G1 -#ifdef ASSERT - // mangle it so any problems will show up - __ set(0xdeadbeef, I0); - __ set(0xdeadbeef, I1); -#endif - } -#endif // TIERED __ set((intptr_t)os::get_polling_page(), L0); __ relocate(relocInfo::poll_return_type); __ ld_ptr(L0, 0, G0); @@ -1568,23 +1483,11 @@ void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, Register xhi = opr1->as_register_hi(); if (opr2->is_constant() && opr2->as_jlong() == 0) { assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "only handles these cases"); -#ifdef _LP64 __ orcc(xhi, G0, G0); -#else - __ orcc(xhi, xlo, G0); -#endif } else if (opr2->is_register()) { Register ylo = opr2->as_register_lo(); Register yhi = opr2->as_register_hi(); -#ifdef _LP64 __ cmp(xlo, ylo); -#else - __ subcc(xlo, ylo, xlo); - __ subccc(xhi, yhi, xhi); - if (condition == lir_cond_equal || condition == lir_cond_notEqual) { - __ orcc(xhi, xlo, G0); - } -#endif } else { ShouldNotReachHere(); } @@ -1612,13 +1515,7 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op ShouldNotReachHere(); } } else if (code == lir_cmp_l2i) { -#ifdef _LP64 __ lcmp(left->as_register_lo(), right->as_register_lo(), dst->as_register()); -#else - __ lcmp(left->as_register_hi(), left->as_register_lo(), - right->as_register_hi(), right->as_register_lo(), - dst->as_register()); -#endif } else { ShouldNotReachHere(); } @@ -1656,12 +1553,11 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L ShouldNotReachHere(); } Label skip; -#ifdef _LP64 if (type == T_INT) { __ br(acond, false, Assembler::pt, skip); - } else -#endif + } else { __ brx(acond, false, Assembler::pt, skip); // checks icc on 32bit and xcc on 64bit + } if (opr1->is_constant() && opr1->type() == T_INT) { Register dest = result->as_register(); if (Assembler::is_simm13(opr1->as_jint())) { @@ -1720,7 +1616,6 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr } } else if (dest->is_double_cpu()) { -#ifdef _LP64 Register dst_lo = dest->as_register_lo(); Register op1_lo = left->as_pointer_register(); Register op2_lo = right->as_pointer_register(); @@ -1736,28 +1631,6 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr default: ShouldNotReachHere(); } -#else - Register op1_lo = left->as_register_lo(); - Register op1_hi = left->as_register_hi(); - Register op2_lo = right->as_register_lo(); - Register op2_hi = right->as_register_hi(); - Register dst_lo = dest->as_register_lo(); - Register dst_hi = dest->as_register_hi(); - - switch (code) { - case lir_add: - __ addcc(op1_lo, op2_lo, dst_lo); - __ addc (op1_hi, op2_hi, dst_hi); - break; - - case lir_sub: - __ subcc(op1_lo, op2_lo, dst_lo); - __ subc (op1_hi, op2_hi, dst_hi); - break; - - default: ShouldNotReachHere(); - } -#endif } else { assert (right->is_single_cpu(), "Just Checking"); @@ -1852,23 +1725,14 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr int simm13 = (int)c; switch (code) { case lir_logic_and: -#ifndef _LP64 - __ and3 (left->as_register_hi(), 0, dest->as_register_hi()); -#endif __ and3 (left->as_register_lo(), simm13, dest->as_register_lo()); break; case lir_logic_or: -#ifndef _LP64 - __ or3 (left->as_register_hi(), 0, dest->as_register_hi()); -#endif __ or3 (left->as_register_lo(), simm13, dest->as_register_lo()); break; case lir_logic_xor: -#ifndef _LP64 - __ xor3 (left->as_register_hi(), 0, dest->as_register_hi()); -#endif __ xor3 (left->as_register_lo(), simm13, dest->as_register_lo()); break; @@ -1886,7 +1750,6 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr default: ShouldNotReachHere(); } } else { -#ifdef _LP64 Register l = (left->is_single_cpu() && left->is_oop_register()) ? left->as_register() : left->as_register_lo(); Register r = (right->is_single_cpu() && right->is_oop_register()) ? right->as_register() : @@ -1898,26 +1761,6 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr case lir_logic_xor: __ xor3 (l, r, dest->as_register_lo()); break; default: ShouldNotReachHere(); } -#else - switch (code) { - case lir_logic_and: - __ and3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); - __ and3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); - break; - - case lir_logic_or: - __ or3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); - __ or3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); - break; - - case lir_logic_xor: - __ xor3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); - __ xor3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); - break; - - default: ShouldNotReachHere(); - } -#endif } } } @@ -1975,12 +1818,10 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL; if (basic_type == T_ARRAY) basic_type = T_OBJECT; -#ifdef _LP64 // higher 32bits must be null __ sra(dst_pos, 0, dst_pos); __ sra(src_pos, 0, src_pos); __ sra(length, 0, length); -#endif // set up the arraycopy stub information ArrayCopyStub* stub = op->stub(); @@ -2316,7 +2157,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) { if (dest->is_single_cpu()) { -#ifdef _LP64 if (left->type() == T_OBJECT) { switch (code) { case lir_shl: __ sllx (left->as_register(), count->as_register(), dest->as_register()); break; @@ -2325,7 +2165,6 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr default: ShouldNotReachHere(); } } else -#endif switch (code) { case lir_shl: __ sll (left->as_register(), count->as_register(), dest->as_register()); break; case lir_shr: __ sra (left->as_register(), count->as_register(), dest->as_register()); break; @@ -2333,27 +2172,17 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr default: ShouldNotReachHere(); } } else { -#ifdef _LP64 switch (code) { case lir_shl: __ sllx (left->as_register_lo(), count->as_register(), dest->as_register_lo()); break; case lir_shr: __ srax (left->as_register_lo(), count->as_register(), dest->as_register_lo()); break; case lir_ushr: __ srlx (left->as_register_lo(), count->as_register(), dest->as_register_lo()); break; default: ShouldNotReachHere(); } -#else - switch (code) { - case lir_shl: __ lshl (left->as_register_hi(), left->as_register_lo(), count->as_register(), dest->as_register_hi(), dest->as_register_lo(), G3_scratch); break; - case lir_shr: __ lshr (left->as_register_hi(), left->as_register_lo(), count->as_register(), dest->as_register_hi(), dest->as_register_lo(), G3_scratch); break; - case lir_ushr: __ lushr (left->as_register_hi(), left->as_register_lo(), count->as_register(), dest->as_register_hi(), dest->as_register_lo(), G3_scratch); break; - default: ShouldNotReachHere(); - } -#endif } } void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) { -#ifdef _LP64 if (left->type() == T_OBJECT) { count = count & 63; // shouldn't shift by more than sizeof(intptr_t) Register l = left->as_register(); @@ -2366,7 +2195,6 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr de } return; } -#endif if (dest->is_single_cpu()) { count = count & 0x1F; // Java spec @@ -2425,7 +2253,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { op->tmp4()->as_register() == O1 && op->klass()->as_register() == G5, "must be"); - LP64_ONLY( __ signx(op->len()->as_register()); ) + __ signx(op->len()->as_register()); if (UseSlowPath || (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { @@ -2748,7 +2576,6 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { Register new_value_hi = op->new_value()->as_register_hi(); Register t1 = op->tmp1()->as_register(); Register t2 = op->tmp2()->as_register(); -#ifdef _LP64 __ mov(cmp_value_lo, t1); __ mov(new_value_lo, t2); // perform the compare and swap operation @@ -2756,23 +2583,6 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { // generate condition code - if the swap succeeded, t2 ("new value" reg) was // overwritten with the original value in "addr" and will be equal to t1. __ cmp(t1, t2); -#else - // move high and low halves of long values into single registers - __ sllx(cmp_value_hi, 32, t1); // shift high half into temp reg - __ srl(cmp_value_lo, 0, cmp_value_lo); // clear upper 32 bits of low half - __ or3(t1, cmp_value_lo, t1); // t1 holds 64-bit compare value - __ sllx(new_value_hi, 32, t2); - __ srl(new_value_lo, 0, new_value_lo); - __ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap - // perform the compare and swap operation - __ casx(addr, t1, t2); - // generate condition code - if the swap succeeded, t2 ("new value" reg) was - // overwritten with the original value in "addr" and will be equal to t1. - // Produce icc flag for 32bit. - __ sub(t1, t2, t2); - __ srlx(t2, 32, t1); - __ orcc(t2, t1, G0); -#endif } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { Register addr = op->addr()->as_pointer_register(); Register cmp_value = op->cmp_value()->as_register(); @@ -2914,13 +2724,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { assert(data->is_CounterData(), "need CounterData for calls"); assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); Register mdo = op->mdo()->as_register(); -#ifdef _LP64 assert(op->tmp1()->is_double_cpu(), "tmp1 must be allocated"); Register tmp1 = op->tmp1()->as_register_lo(); -#else - assert(op->tmp1()->is_single_cpu(), "tmp1 must be allocated"); - Register tmp1 = op->tmp1()->as_register(); -#endif metadata2reg(md->constant_encoding(), mdo); int mdo_offset_bias = 0; if (!Assembler::is_simm13(md->byte_offset_of_slot(data, CounterData::count_offset()) + @@ -3200,12 +3005,7 @@ void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest) { assert (left->is_double_cpu(), "Must be a long"); Register Rlow = left->as_register_lo(); Register Rhi = left->as_register_hi(); -#ifdef _LP64 __ sub(G0, Rlow, dest->as_register_lo()); -#else - __ subcc(G0, Rlow, dest->as_register_lo()); - __ subc (G0, Rhi, dest->as_register_hi()); -#endif } } @@ -3245,9 +3045,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { -#ifdef _LP64 ShouldNotReachHere(); -#endif NEEDS_CLEANUP; if (type == T_LONG) { @@ -3491,31 +3289,6 @@ void LIR_Assembler::peephole(LIR_List* lir) { inst->insert_before(i + 1, delay_op); i++; } - -#if defined(TIERED) && !defined(_LP64) - // fixup the return value from G1 to O0/O1 for long returns. - // It's done here instead of in LIRGenerator because there's - // such a mismatch between the single reg and double reg - // calling convention. - LIR_OpJavaCall* callop = op->as_OpJavaCall(); - if (callop->result_opr() == FrameMap::out_long_opr) { - LIR_OpJavaCall* call; - LIR_OprList* arguments = new LIR_OprList(callop->arguments()->length()); - for (int a = 0; a < arguments->length(); a++) { - arguments[a] = callop->arguments()[a]; - } - if (op->code() == lir_virtual_call) { - call = new LIR_OpJavaCall(op->code(), callop->method(), callop->receiver(), FrameMap::g1_long_single_opr, - callop->vtable_offset(), arguments, callop->info()); - } else { - call = new LIR_OpJavaCall(op->code(), callop->method(), callop->receiver(), FrameMap::g1_long_single_opr, - callop->addr(), arguments, callop->info()); - } - inst->at_put(i - 1, call); - inst->insert_before(i + 1, new LIR_Op1(lir_unpack64, FrameMap::g1_long_single_opr, callop->result_opr(), - T_LONG, lir_patch_none, NULL)); - } -#endif break; } } @@ -3533,14 +3306,10 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr } else if (data->is_oop()) { Register obj = data->as_register(); Register narrow = tmp->as_register(); -#ifdef _LP64 assert(UseCompressedOops, "swap is 32bit only"); __ encode_heap_oop(obj, narrow); __ swap(as_Address(addr), narrow); __ decode_heap_oop(narrow, obj); -#else - __ swap(as_Address(addr), obj); -#endif } else { ShouldNotReachHere(); } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp index c46d0002af3..37a3b38cfb3 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -61,11 +61,7 @@ ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias); enum { -#ifdef _LP64 _call_stub_size = 68, -#else - _call_stub_size = 20, -#endif // _LP64 _call_aot_stub_size = 0, _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128), _deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 069b9a2f46e..d1d5532ff45 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -70,7 +70,7 @@ LIR_Opr LIRGenerator::exceptionOopOpr() { return FrameMap::Oexcepti LIR_Opr LIRGenerator::exceptionPcOpr() { return FrameMap::Oissuing_pc_opr; } LIR_Opr LIRGenerator::syncLockOpr() { return new_register(T_INT); } LIR_Opr LIRGenerator::syncTempOpr() { return new_register(T_OBJECT); } -LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); } +LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(T_LONG); } LIR_Opr LIRGenerator::result_register_for(ValueType* type, bool callee) { LIR_Opr opr; @@ -215,13 +215,11 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o } } } else { -#ifdef _LP64 if (index_opr->type() == T_INT) { LIR_Opr tmp = new_register(T_LONG); __ convert(Bytecodes::_i2l, index_opr, tmp); index_opr = tmp; } -#endif base_opr = new_pointer_register(); assert (index_opr->is_register(), "Must be register"); @@ -1317,20 +1315,12 @@ void LIRGenerator::trace_block_entry(BlockBegin* block) { void LIRGenerator::volatile_field_store(LIR_Opr value, LIR_Address* address, CodeEmitInfo* info) { -#ifdef _LP64 __ store(value, address, info); -#else - __ volatile_store_mem_reg(value, address, info); -#endif } void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result, CodeEmitInfo* info) { -#ifdef _LP64 __ load(address, result, info); -#else - __ volatile_load_mem_reg(address, result, info); -#endif } @@ -1340,11 +1330,6 @@ void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data, LIR_Opr index_op = offset; bool is_obj = (type == T_ARRAY || type == T_OBJECT); -#ifndef _LP64 - if (is_volatile && type == T_LONG) { - __ volatile_store_unsafe_reg(data, src, offset, type, NULL, lir_patch_none); - } else -#endif { if (type == T_BOOLEAN) { type = T_BYTE; @@ -1374,11 +1359,6 @@ void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data, void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset, BasicType type, bool is_volatile) { -#ifndef _LP64 - if (is_volatile && type == T_LONG) { - __ volatile_load_unsafe_reg(src, offset, dst, type, NULL, lir_patch_none); - } else -#endif { LIR_Address* addr = new LIR_Address(src, offset, type); __ load(addr, dst); @@ -1403,17 +1383,13 @@ void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { // Because we want a 2-arg form of xchg __ move(data, dst); - assert (!x->is_add() && (type == T_INT || (is_obj LP64_ONLY(&& UseCompressedOops))), "unexpected type"); + assert (!x->is_add() && (type == T_INT || (is_obj && UseCompressedOops)), "unexpected type"); LIR_Address* addr; if (offset->is_constant()) { -#ifdef _LP64 jlong l = offset->as_jlong(); assert((jlong)((jint)l) == l, "offset too large for constant"); jint c = (jint)l; -#else - jint c = offset->as_jint(); -#endif addr = new LIR_Address(src.result(), c, type); } else { addr = new LIR_Address(src.result(), offset, type); diff --git a/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp index e9467760679..c21d2c1d9ad 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp @@ -48,16 +48,9 @@ LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) { void LIR_Address::verify() const { assert(scale() == times_1, "Scaled addressing mode not available on SPARC and should not be used"); assert(disp() == 0 || index()->is_illegal(), "can't have both"); -#ifdef _LP64 assert(base()->is_cpu_register(), "wrong base operand"); assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand"); assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA, "wrong type for addresses"); -#else - assert(base()->is_single_cpu(), "wrong base operand"); - assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand"); - assert(base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA, - "wrong type for addresses"); -#endif } #endif // PRODUCT diff --git a/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp index 164c000de21..6656056bb6f 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -32,11 +32,7 @@ inline bool LinearScan::is_processed_reg_num(int reg_num) { inline int LinearScan::num_physical_regs(BasicType type) { // Sparc requires two cpu registers for long // and two cpu registers for double -#ifdef _LP64 if (type == T_DOUBLE) { -#else - if (type == T_DOUBLE || type == T_LONG) { -#endif return 2; } return 1; @@ -44,11 +40,7 @@ inline int LinearScan::num_physical_regs(BasicType type) { inline bool LinearScan::requires_adjacent_regs(BasicType type) { -#ifdef _LP64 return type == T_DOUBLE; -#else - return type == T_DOUBLE || type == T_LONG; -#endif } inline bool LinearScan::is_caller_save(int assigned_reg) { diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index fbd0e1ce6b4..fa0cde6e6ed 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -273,13 +273,6 @@ void C1_MacroAssembler::initialize_object( add(obj, hdr_size_in_bytes, t1); // compute address of first element sub(var_size_in_bytes, hdr_size_in_bytes, t2); // compute size of body initialize_body(t1, t2); -#ifndef _LP64 - } else if (con_size_in_bytes < threshold * 2) { - // on v9 we can do double word stores to fill twice as much space. - assert(hdr_size_in_bytes % 8 == 0, "double word aligned"); - assert(con_size_in_bytes % 8 == 0, "double word aligned"); - for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += 2 * HeapWordSize) stx(G0, obj, i); -#endif } else if (con_size_in_bytes <= threshold) { // use explicit NULL stores for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += HeapWordSize) st_ptr(G0, obj, i); diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 40e30551967..817e674f36c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -930,11 +930,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { Label not_already_dirty, restart, refill, young_card; -#ifdef _LP64 __ srlx(addr, CardTableModRefBS::card_shift, addr); -#else - __ srl(addr, CardTableModRefBS::card_shift, addr); -#endif AddressLiteral rs(byte_map_base); __ set(rs, cardtable); // cardtable := diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index 10e6799f21e..1fc5948d116 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -66,7 +66,6 @@ define_pd_global(bool, OptoRegScheduling, false); define_pd_global(bool, SuperWordLoopUnrollAnalysis, false); define_pd_global(bool, IdealizeClearArrayNode, true); -#ifdef _LP64 // We need to make sure that all generated code is within // 2 gigs of the libjvm.so runtime routines so we can use // the faster "call" instruction rather than the expensive @@ -82,17 +81,6 @@ define_pd_global(intx, CodeCacheExpansionSize, 64*K); // Ergonomics related flags define_pd_global(uint64_t,MaxRAM, 128ULL*G); -#else -// InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(intx, InitialCodeCacheSize, 1536*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(intx, ReservedCodeCacheSize, 32*M); -define_pd_global(intx, NonProfiledCodeHeapSize, 13*M); -define_pd_global(intx, ProfiledCodeHeapSize, 14*M); -define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(intx, CodeCacheExpansionSize, 32*K); -// Ergonomics related flags -define_pd_global(uint64_t, MaxRAM, 4ULL*G); -#endif define_pd_global(uintx, CodeCacheMinBlockLength, 4); define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); diff --git a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp index a9107d8dfdd..ae1dd0b5dcf 100644 --- a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -114,14 +114,8 @@ static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { } static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { -#ifdef _LP64 assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); pd_conjoint_oops_atomic((oop*)from, (oop*)to, count); -#else - // Guarantee use of ldd/std via some asm code, because compiler won't. - // See solaris_sparc.il. - _Copy_conjoint_jlongs_atomic(from, to, count); -#endif } static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) { @@ -162,7 +156,6 @@ static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) } static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { -#ifdef _LP64 guarantee(mask_bits((uintptr_t)tohw, right_n_bits(LogBytesPerLong)) == 0, "unaligned fill words"); julong* to = (julong*)tohw; @@ -170,12 +163,6 @@ static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { while (count-- > 0) { *to++ = v; } -#else // _LP64 - juint* to = (juint*)tohw; - while (count-- > 0) { - *to++ = value; - } -#endif // _LP64 } typedef void (*_zero_Fn)(HeapWord* to, size_t count); diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp index c666f1eca47..2b1f5e66b65 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -114,11 +114,7 @@ address RegisterMap::pd_location(VMReg regname) const { // register locations. When that is fixed we'd will return NULL // (or assert here). reg = regname->prev()->as_Register(); -#ifdef _LP64 second_word = sizeof(jint); -#else - return NULL; -#endif // _LP64 } else { reg = regname->as_Register(); } @@ -332,9 +328,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Construct an unpatchable, deficient frame void frame::init(intptr_t* sp, address pc, CodeBlob* cb) { -#ifdef _LP64 assert( (((intptr_t)sp & (wordSize-1)) == 0), "frame constructor passed an invalid sp"); -#endif _sp = sp; _younger_sp = NULL; _pc = pc; @@ -693,11 +687,9 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) intptr_t* d_scratch = fp() + interpreter_frame_d_scratch_fp_offset; address l_addr = (address)l_scratch; -#ifdef _LP64 // On 64-bit the result for 1/8/16/32-bit result types is in the other // word half l_addr += wordSize/2; -#endif switch (type) { case T_OBJECT: diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp index 48cf45bd714..b3f16e4e377 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -100,11 +100,7 @@ // size of each block, in order of increasing address: register_save_words = 16, -#ifdef _LP64 callee_aggregate_return_pointer_words = 0, -#else - callee_aggregate_return_pointer_words = 1, -#endif callee_register_argument_save_area_words = 6, // memory_parameter_words = , diff --git a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp index ba6d99cd8ea..465a6a014e3 100644 --- a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -38,24 +38,14 @@ const bool CCallingConventionRequiresIntsAsLongs = true; // The expected size in bytes of a cache line, used to pad data structures. #if defined(TIERED) - #ifdef _LP64 - // tiered, 64-bit, large machine - #define DEFAULT_CACHE_LINE_SIZE 128 - #else - // tiered, 32-bit, medium machine - #define DEFAULT_CACHE_LINE_SIZE 64 - #endif + // tiered, 64-bit, large machine + #define DEFAULT_CACHE_LINE_SIZE 128 #elif defined(COMPILER1) // pure C1, 32-bit, small machine #define DEFAULT_CACHE_LINE_SIZE 16 #elif defined(COMPILER2) || defined(SHARK) - #ifdef _LP64 - // pure C2, 64-bit, large machine - #define DEFAULT_CACHE_LINE_SIZE 128 - #else - // pure C2, 32-bit, medium machine - #define DEFAULT_CACHE_LINE_SIZE 64 - #endif + // pure C2, 64-bit, large machine + #define DEFAULT_CACHE_LINE_SIZE 128 #endif #if defined(SOLARIS) diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index ae9ba7e467f..c25dab7a84e 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -56,18 +56,10 @@ define_pd_global(intx, InlineSmallCode, 1500); #define DEFAULT_STACK_RED_PAGES (1) #define DEFAULT_STACK_RESERVED_PAGES (SOLARIS_ONLY(1) NOT_SOLARIS(0)) -#ifdef _LP64 -// Stack slots are 2X larger in LP64 than in the 32 bit VM. define_pd_global(intx, CompilerThreadStackSize, 1024); define_pd_global(intx, ThreadStackSize, 1024); define_pd_global(intx, VMThreadStackSize, 1024); #define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2)) -#else -define_pd_global(intx, CompilerThreadStackSize, 512); -define_pd_global(intx, ThreadStackSize, 512); -define_pd_global(intx, VMThreadStackSize, 512); -#define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2)) -#endif // _LP64 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES #define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES diff --git a/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp b/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp index d6942f6a7ca..5b384514489 100644 --- a/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -32,13 +32,9 @@ #include "oops/oop.inline.hpp" int InlineCacheBuffer::ic_stub_code_size() { -#ifdef _LP64 return (NativeMovConstReg::instruction_size + // sethi;add NativeJump::instruction_size + // sethi; jmp; delay slot (1*BytesPerInstWord) + 1); // flush + 1 extra byte -#else - return (2+2+ 1) * wordSize + 1; // set/jump_to/nop + 1 byte so that code_end can be set in CodeBuffer -#endif } void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index ef2362897f7..dbcf11532d4 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -39,11 +39,6 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" -#ifndef FAST_DISPATCH -#define FAST_DISPATCH 1 -#endif -#undef FAST_DISPATCH - // Implementation of InterpreterMacroAssembler // This file specializes the assember with interpreter-specific macros @@ -78,23 +73,12 @@ void InterpreterMacroAssembler::compute_extra_locals_size_in_bytes(Register args // own dispatch. The dispatch address is computed and placed in IdispatchAddress void InterpreterMacroAssembler::dispatch_prolog(TosState state, int bcp_incr) { assert_not_delayed(); -#ifdef FAST_DISPATCH - // FAST_DISPATCH and ProfileInterpreter are mutually exclusive since - // they both use I2. - assert(!ProfileInterpreter, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive"); - ldub(Lbcp, bcp_incr, Lbyte_code); // load next bytecode - add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); - // add offset to correct dispatch table - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize - ld_ptr(IdispatchTables, Lbyte_code, IdispatchAddress);// get entry addr -#else ldub( Lbcp, bcp_incr, Lbyte_code); // load next bytecode // dispatch table to use AddressLiteral tbl(Interpreter::dispatch_table(state)); sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize set(tbl, G3_scratch); // compute addr of table ld_ptr(G3_scratch, Lbyte_code, IdispatchAddress); // get entry addr -#endif } @@ -281,23 +265,11 @@ void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, address* tab // %%%%% maybe implement +VerifyActivationFrameSize here //verify_thread(); //too slow; we will just verify on method entry & exit if (verify) interp_verify_oop(Otos_i, state, __FILE__, __LINE__); -#ifdef FAST_DISPATCH - if (table == Interpreter::dispatch_table(state)) { - // use IdispatchTables - add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); - // add offset to correct dispatch table - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize - ld_ptr(IdispatchTables, Lbyte_code, G3_scratch); // get entry addr - } else { -#endif - // dispatch table to use - AddressLiteral tbl(table); - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize - set(tbl, G3_scratch); // compute addr of table - ld_ptr(G3_scratch, Lbyte_code, G3_scratch); // get entry addr -#ifdef FAST_DISPATCH - } -#endif + // dispatch table to use + AddressLiteral tbl(table); + sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize + set(tbl, G3_scratch); // compute addr of table + ld_ptr(G3_scratch, Lbyte_code, G3_scratch); // get entry addr jmp( G3_scratch, 0 ); if (bcp_incr != 0) delayed()->inc(Lbcp, bcp_incr); else delayed()->nop(); @@ -318,52 +290,32 @@ void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, address* tab void InterpreterMacroAssembler::load_unaligned_double(Register r1, int offset, FloatRegister d) { assert_not_delayed(); -#ifdef _LP64 ldf(FloatRegisterImpl::D, r1, offset, d); -#else - ldf(FloatRegisterImpl::S, r1, offset, d); - ldf(FloatRegisterImpl::S, r1, offset + Interpreter::stackElementSize, d->successor()); -#endif } // Known good alignment in _LP64 but unknown otherwise void InterpreterMacroAssembler::store_unaligned_double(FloatRegister d, Register r1, int offset) { assert_not_delayed(); -#ifdef _LP64 stf(FloatRegisterImpl::D, d, r1, offset); // store something more useful here debug_only(stx(G0, r1, offset+Interpreter::stackElementSize);) -#else - stf(FloatRegisterImpl::S, d, r1, offset); - stf(FloatRegisterImpl::S, d->successor(), r1, offset + Interpreter::stackElementSize); -#endif } // Known good alignment in _LP64 but unknown otherwise void InterpreterMacroAssembler::load_unaligned_long(Register r1, int offset, Register rd) { assert_not_delayed(); -#ifdef _LP64 ldx(r1, offset, rd); -#else - ld(r1, offset, rd); - ld(r1, offset + Interpreter::stackElementSize, rd->successor()); -#endif } // Known good alignment in _LP64 but unknown otherwise void InterpreterMacroAssembler::store_unaligned_long(Register l, Register r1, int offset) { assert_not_delayed(); -#ifdef _LP64 stx(l, r1, offset); // store something more useful here stx(G0, r1, offset+Interpreter::stackElementSize); -#else - st(l, r1, offset); - st(l->successor(), r1, offset + Interpreter::stackElementSize); -#endif } void InterpreterMacroAssembler::pop_i(Register r) { @@ -527,9 +479,7 @@ void InterpreterMacroAssembler::empty_expression_stack() { sub( Lesp, Gframe_size, Gframe_size ); and3( Gframe_size, -(2 * wordSize), Gframe_size ); // align SP (downwards) to an 8/16-byte boundary debug_only(verify_sp(Gframe_size, G4_scratch)); -#ifdef _LP64 sub(Gframe_size, STACK_BIAS, Gframe_size ); -#endif mov(Gframe_size, SP); bind(done); @@ -541,28 +491,20 @@ void InterpreterMacroAssembler::verify_sp(Register Rsp, Register Rtemp) { Label Bad, OK; // Saved SP must be aligned. -#ifdef _LP64 btst(2*BytesPerWord-1, Rsp); -#else - btst(LongAlignmentMask, Rsp); -#endif br(Assembler::notZero, false, Assembler::pn, Bad); delayed()->nop(); // Saved SP, plus register window size, must not be above FP. add(Rsp, frame::register_save_words * wordSize, Rtemp); -#ifdef _LP64 sub(Rtemp, STACK_BIAS, Rtemp); // Bias Rtemp before cmp to FP -#endif cmp_and_brx_short(Rtemp, FP, Assembler::greaterUnsigned, Assembler::pn, Bad); // Saved SP must not be ridiculously below current SP. size_t maxstack = MAX2(JavaThread::stack_size_at_create(), (size_t) 4*K*K); set(maxstack, Rtemp); sub(SP, Rtemp, Rtemp); -#ifdef _LP64 add(Rtemp, STACK_BIAS, Rtemp); // Unbias Rtemp before cmp to Rsp -#endif cmp_and_brx_short(Rsp, Rtemp, Assembler::lessUnsigned, Assembler::pn, Bad); ba_short(OK); @@ -584,9 +526,7 @@ void InterpreterMacroAssembler::verify_esp(Register Resp) { delayed()->sub(Resp, frame::memory_parameter_word_sp_offset * wordSize, Resp); stop("too many pops: Lesp points into monitor area"); bind(OK1); -#ifdef _LP64 sub(Resp, STACK_BIAS, Resp); -#endif cmp(Resp, SP); brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, OK2); delayed()->add(Resp, STACK_BIAS + frame::memory_parameter_word_sp_offset * wordSize, Resp); @@ -696,21 +636,12 @@ void InterpreterMacroAssembler::get_4_byte_integer_at_bcp( } br(Assembler::zero, true, Assembler::pn, aligned); -#ifdef _LP64 delayed()->ldsw(Rtmp, 0, Rdst); -#else - delayed()->ld(Rtmp, 0, Rdst); -#endif ldub(Lbcp, bcp_offset + 3, Rdst); ldub(Lbcp, bcp_offset + 2, Rtmp); sll(Rtmp, 8, Rtmp); or3(Rtmp, Rdst, Rdst); ldub(Lbcp, bcp_offset + 1, Rtmp); sll(Rtmp, 16, Rtmp); or3(Rtmp, Rdst, Rdst); -#ifdef _LP64 ldsb(Lbcp, bcp_offset + 0, Rtmp); sll(Rtmp, 24, Rtmp); -#else - // Unsigned load is faster than signed on some implementations - ldub(Lbcp, bcp_offset + 0, Rtmp); sll(Rtmp, 24, Rtmp); -#endif or3(Rtmp, Rdst, Rdst ); bind(aligned); @@ -796,7 +727,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( sll(index, LogBytesPerHeapOop, tmp); get_constant_pool(result); // load pointer for resolved_references[] objArray - ld_ptr(result, ConstantPool::resolved_references_offset_in_bytes(), result); + ld_ptr(result, ConstantPool::cache_offset_in_bytes(), result); + ld_ptr(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result); // JNIHandles::resolve(result) ld_ptr(result, 0, result); // Add in the index @@ -805,6 +737,24 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool, + Register Roffset, Register Rklass) { + // int value = *this_cp->int_at_addr(which); + // int resolved_klass_index = extract_low_short_from_int(value); + // + // Because SPARC is big-endian, the low_short is at (cpool->int_at_addr(which) + 2 bytes) + add(Roffset, Rcpool, Roffset); + lduh(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index + + Register Rresolved_klasses = Rklass; + ld_ptr(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes(), Rresolved_klasses); + sll(Roffset, LogBytesPerWord, Roffset); + add(Roffset, Array::base_offset_in_bytes(), Roffset); + ld_ptr(Rresolved_klasses, Roffset, Rklass); +} + + // Generate a subtype check: branch to ok_is_subtype if sub_klass is // a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2. void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, @@ -910,10 +860,8 @@ void InterpreterMacroAssembler::index_check_without_pop(Register array, Register assert_not_delayed(); verify_oop(array); -#ifdef _LP64 // sign extend since tos (index) can be a 32bit value sra(index, G0, index); -#endif // _LP64 // check array Label ptr_ok; @@ -1191,11 +1139,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, // return tos assert(Otos_l1 == Otos_i, "adjust code below"); switch (state) { -#ifdef _LP64 case ltos: mov(Otos_l, Otos_l->after_save()); break; // O0 -> I0 -#else - case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 -#endif case btos: // fall through case ztos: // fall through case ctos: @@ -1207,20 +1151,6 @@ void InterpreterMacroAssembler::remove_activation(TosState state, case vtos: /* nothing to do */ break; default : ShouldNotReachHere(); } - -#if defined(COMPILER2) && !defined(_LP64) - if (state == ltos) { - // C2 expects long results in G1 we can't tell if we're returning to interpreted - // or compiled so just be safe use G1 and O0/O1 - - // Shift bits into high (msb) of G1 - sllx(Otos_l1->after_save(), 32, G1); - // Zero extend low bits - srl (Otos_l2->after_save(), 0, Otos_l2->after_save()); - or3 (Otos_l2->after_save(), G1, G1); - } -#endif /* COMPILER2 */ - } // Lock object @@ -1270,9 +1200,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg, Register Object) // Check if owner is self by comparing the value in the markOop of object // with the stack pointer sub(temp_reg, SP, temp_reg); -#ifdef _LP64 sub(temp_reg, STACK_BIAS, temp_reg); -#endif assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); // Composite "andcc" test: @@ -2711,11 +2639,7 @@ void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, void InterpreterMacroAssembler::save_return_value(TosState state, bool is_native_call) { if (is_native_call) { stf(FloatRegisterImpl::D, F0, d_tmp); -#ifdef _LP64 stx(O0, l_tmp); -#else - std(O0, l_tmp); -#endif } else { push(state); } @@ -2724,11 +2648,7 @@ void InterpreterMacroAssembler::save_return_value(TosState state, bool is_native void InterpreterMacroAssembler::restore_return_value( TosState state, bool is_native_call) { if (is_native_call) { ldf(FloatRegisterImpl::D, d_tmp, F0); -#ifdef _LP64 ldx(l_tmp, O0); -#else - ldd(l_tmp, O0); -#endif } else { pop(state); } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 1baceb1233c..23e85374904 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -70,9 +70,6 @@ class InterpreterMacroAssembler: public MacroAssembler { bool check_exception=true ); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table); @@ -80,6 +77,9 @@ class InterpreterMacroAssembler: public MacroAssembler { InterpreterMacroAssembler(CodeBuffer* c) : MacroAssembler(c) {} + virtual void check_and_handle_popframe(Register scratch_reg); + virtual void check_and_handle_earlyret(Register scratch_reg); + void jump_to_entry(address entry); virtual void load_earlyret_value(TosState state); @@ -196,6 +196,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // load cpool->resolved_references(index); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass); + // common code void field_offset_at(int n, Register tmp, Register dest, Register base); diff --git a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp index 0e1d6c992cd..f7cb124486d 100644 --- a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -53,47 +53,24 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_long() { Argument jni_arg(jni_offset(), false); Register Rtmp = O0; -#ifdef _LP64 __ ldx(Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); __ store_long_argument(Rtmp, jni_arg); -#else - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); - __ store_argument(Rtmp, jni_arg); - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset() + 0), Rtmp); - Argument successor(jni_arg.successor()); - __ store_argument(Rtmp, successor); -#endif } void InterpreterRuntime::SignatureHandlerGenerator::pass_float() { Argument jni_arg(jni_offset(), false); -#ifdef _LP64 FloatRegister Rtmp = F0; __ ldf(FloatRegisterImpl::S, Llocals, Interpreter::local_offset_in_bytes(offset()), Rtmp); __ store_float_argument(Rtmp, jni_arg); -#else - Register Rtmp = O0; - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset()), Rtmp); - __ store_argument(Rtmp, jni_arg); -#endif } void InterpreterRuntime::SignatureHandlerGenerator::pass_double() { Argument jni_arg(jni_offset(), false); -#ifdef _LP64 FloatRegister Rtmp = F0; __ ldf(FloatRegisterImpl::D, Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); __ store_double_argument(Rtmp, jni_arg); -#else - Register Rtmp = O0; - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); - __ store_argument(Rtmp, jni_arg); - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset()), Rtmp); - Argument successor(jni_arg.successor()); - __ store_argument(Rtmp, successor); -#endif } void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { @@ -171,7 +148,6 @@ class SlowSignatureHandler: public NativeSignatureIterator { add_signature( non_float ); } -#ifdef _LP64 virtual void pass_float() { *_to++ = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); _from -= Interpreter::stackElementSize; @@ -190,23 +166,6 @@ class SlowSignatureHandler: public NativeSignatureIterator { _from -= 2*Interpreter::stackElementSize; add_signature( long_sig ); } -#else - // pass_double() is pass_long() and pass_float() only _LP64 - virtual void pass_long() { - _to[0] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - _to[1] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(0)); - _to += 2; - _from -= 2*Interpreter::stackElementSize; - add_signature( non_float ); - } - - virtual void pass_float() { - *_to++ = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - _from -= Interpreter::stackElementSize; - add_signature( non_float ); - } - -#endif // _LP64 virtual void add_signature( intptr_t sig_type ) { if ( _argcount < (sizeof (intptr_t))*4 ) { diff --git a/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp b/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp index 1b4b3bf2ffc..c51545c09cc 100644 --- a/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -88,9 +88,7 @@ private: // _last_Java_sp will always be a an unbiased stack pointer // if is is biased then some setter screwed up. This is // deadly. -#ifdef _LP64 assert(((intptr_t)_last_Java_sp & 0xF) == 0, "Biased last_Java_sp"); -#endif return _last_Java_sp; } diff --git a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp index ff9fcd69472..178b9c74870 100644 --- a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp @@ -152,39 +152,19 @@ address JNI_FastGetField::generate_fast_get_long_field() { __ ld_ptr (O1, 0, O5); __ add (O5, O4, O5); -#ifndef _LP64 - assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small"); - speculative_load_pclist[count++] = __ pc(); - __ ld (O5, 0, G2); - - speculative_load_pclist[count] = __ pc(); - __ ld (O5, 4, O3); -#else assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); speculative_load_pclist[count] = __ pc(); __ ldx (O5, 0, O3); -#endif __ ld (cnt_addr, G1); __ cmp (G1, G4); __ br (Assembler::notEqual, false, Assembler::pn, label2); __ delayed()->mov (O7, G1); -#ifndef _LP64 - __ mov (G2, O0); - __ retl (); - __ delayed()->mov (O3, O1); -#else __ retl (); __ delayed()->mov (O3, O0); -#endif -#ifndef _LP64 - slowcase_entry_pclist[count-1] = __ pc(); - slowcase_entry_pclist[count++] = __ pc() ; -#else slowcase_entry_pclist[count++] = __ pc(); -#endif __ bind (label1); __ mov (O7, G1); diff --git a/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp b/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp index 9c3049141fd..50b51fff2c3 100644 --- a/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -55,18 +55,10 @@ public: static inline void put_int(jint from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = from; } static inline void put_int(jint *from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = *from; } -#ifdef _LP64 // Longs are stored in native format in one JavaCallArgument slot at *(to+1). static inline void put_long(jlong from, intptr_t *to) { *(jlong *)(to + 1 + 0) = from; } static inline void put_long(jlong from, intptr_t *to, int& pos) { *(jlong *)(to + 1 + pos) = from; pos += 2; } static inline void put_long(jlong *from, intptr_t *to, int& pos) { *(jlong *)(to + 1 + pos) = *from; pos += 2; } -#else - // Longs are stored in reversed native word format in two JavaCallArgument slots at *to. - // The high half is in *(to+1) and the low half in *to. - static inline void put_long(jlong from, intptr_t *to) { put_int2r((jint *)&from, (jint *)to); } - static inline void put_long(jlong from, intptr_t *to, int& pos) { put_int2r((jint *)&from, (jint *)to, pos); } - static inline void put_long(jlong *from, intptr_t *to, int& pos) { put_int2r((jint *) from, (jint *)to, pos); } -#endif // Oops are stored in native format in one JavaCallArgument slot at *to. static inline void put_obj(oop from, intptr_t *to) { *(oop *)(to + 0 ) = from; } @@ -78,39 +70,21 @@ public: static inline void put_float(jfloat from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = from; } static inline void put_float(jfloat *from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = *from; } -#ifdef _LP64 // Doubles are stored in native word format in one JavaCallArgument slot at *(to+1). static inline void put_double(jdouble from, intptr_t *to) { *(jdouble *)(to + 1 + 0) = from; } static inline void put_double(jdouble from, intptr_t *to, int& pos) { *(jdouble *)(to + 1 + pos) = from; pos += 2; } static inline void put_double(jdouble *from, intptr_t *to, int& pos) { *(jdouble *)(to + 1 + pos) = *from; pos += 2; } -#else - // Doubles are stored in reversed native word format in two JavaCallArgument slots at *to. - static inline void put_double(jdouble from, intptr_t *to) { put_int2r((jint *)&from, (jint *)to); } - static inline void put_double(jdouble from, intptr_t *to, int& pos) { put_int2r((jint *)&from, (jint *)to, pos); } - static inline void put_double(jdouble *from, intptr_t *to, int& pos) { put_int2r((jint *) from, (jint *)to, pos); } -#endif // The get_xxx routines, on the other hand, actually _do_ fetch // java primitive types from the interpreter stack. static inline jint get_int(intptr_t *from) { return *(jint *)from; } -#ifdef _LP64 static inline jlong get_long(intptr_t *from) { return *(jlong *)from; } -#else - static inline jlong get_long(intptr_t *from) { return ((jlong)(*( signed int *)((jint *)from )) << 32) | - ((jlong)(*(unsigned int *)((jint *)from + 1)) << 0); } -#endif static inline oop get_obj(intptr_t *from) { return *(oop *)from; } static inline jfloat get_float(intptr_t *from) { return *(jfloat *)from; } -#ifdef _LP64 static inline jdouble get_double(intptr_t *from) { return *(jdouble *)from; } -#else - static inline jdouble get_double(intptr_t *from) { jlong jl = ((jlong)(*( signed int *)((jint *)from )) << 32) | - ((jlong)(*(unsigned int *)((jint *)from + 1)) << 0); - return *(jdouble *)&jl; } -#endif }; diff --git a/hotspot/src/cpu/sparc/vm/jni_sparc.h b/hotspot/src/cpu/sparc/vm/jni_sparc.h index a7540600488..3402f67c992 100644 --- a/hotspot/src/cpu/sparc/vm/jni_sparc.h +++ b/hotspot/src/cpu/sparc/vm/jni_sparc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -39,10 +39,6 @@ typedef int jint; -#ifdef _LP64 - typedef long jlong; -#else - typedef long long jlong; -#endif +typedef long jlong; typedef signed char jbyte; diff --git a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp index 4976e1686b2..09f228a6ce9 100644 --- a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -44,16 +44,12 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); if (HotSpotObjectConstantImpl::compressed(constant)) { -#ifdef _LP64 int oop_index = _oop_recorder->find_index(value); RelocationHolder rspec = oop_Relocation::spec(oop_index); _instructions->relocate(pc, rspec, 1); -#else - JVMCI_ERROR("compressed oop on 32bit"); -#endif } else { NativeMovConstReg* move = nativeMovConstReg_at(pc); move->set_data((intptr_t) value); @@ -69,14 +65,10 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; if (HotSpotMetaspaceConstantImpl::compressed(constant)) { -#ifdef _LP64 NativeMovConstReg32* move = nativeMovConstReg32_at(pc); narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, CHECK); move->set_data((intptr_t)narrowOop); TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop); -#else - JVMCI_ERROR("compressed Klass* on 32bit"); -#endif } else { NativeMovConstReg* move = nativeMovConstReg_at(pc); void* reference = record_metadata_reference(_instructions, pc, constant, CHECK); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index e0065402b05..faba67a5747 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -296,11 +296,6 @@ void MacroAssembler::verify_thread() { mov(G3, L3); // avoid clobbering G3 mov(G4, L4); // avoid clobbering G4 mov(G5_method, L5); // avoid clobbering G5_method -#if defined(COMPILER2) && !defined(_LP64) - // Save & restore possible 64-bit Long arguments in G-regs - srlx(G1,32,L0); - srlx(G4,32,L6); -#endif call(CAST_FROM_FN_PTR(address,verify_thread_subroutine), relocInfo::runtime_call_type); delayed()->mov(G2_thread, O0); @@ -309,15 +304,6 @@ void MacroAssembler::verify_thread() { mov(L3, G3); // restore G3 mov(L4, G4); // restore G4 mov(L5, G5_method); // restore G5_method -#if defined(COMPILER2) && !defined(_LP64) - // Save & restore possible 64-bit Long arguments in G-regs - sllx(L0,32,G2); // Move old high G1 bits high in G2 - srl(G1, 0,G1); // Clear current high G1 bits - or3 (G1,G2,G1); // Recover 64-bit G1 - sllx(L6,32,G2); // Move old high G4 bits high in G2 - srl(G4, 0,G4); // Clear current high G4 bits - or3 (G4,G2,G4); // Recover 64-bit G4 -#endif restore(O0, 0, G2_thread); } } @@ -387,7 +373,6 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Ja st_ptr(last_Java_pc, pc_addr); } -#ifdef _LP64 #ifdef ASSERT // Make sure that we have an odd stack Label StackOk; @@ -400,9 +385,6 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Ja assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame"); add( last_java_sp, STACK_BIAS, G4_scratch ); st_ptr(G4_scratch, G2_thread, JavaThread::last_Java_sp_offset()); -#else - st_ptr(last_java_sp, G2_thread, JavaThread::last_Java_sp_offset()); -#endif // _LP64 } void MacroAssembler::reset_last_Java_frame(void) { @@ -658,11 +640,7 @@ void MacroAssembler::ic_call(address entry, bool emit_delay, jint method_index) void MacroAssembler::card_table_write(jbyte* byte_map_base, Register tmp, Register obj) { -#ifdef _LP64 srlx(obj, CardTableModRefBS::card_shift, obj); -#else - srl(obj, CardTableModRefBS::card_shift, obj); -#endif assert(tmp != obj, "need separate temp reg"); set((address) byte_map_base, tmp); stb(G0, tmp, obj); @@ -672,7 +650,6 @@ void MacroAssembler::card_table_write(jbyte* byte_map_base, void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { address save_pc; int shiftcnt; -#ifdef _LP64 # ifdef CHECK_DELAY assert_not_delayed((char*) "cannot put two instructions in delay slot"); # endif @@ -719,9 +696,6 @@ void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, b while (pc() < (save_pc + (7 * BytesPerInstWord))) nop(); } -#else - Assembler::sethi(addrlit.value(), d, addrlit.rspec()); -#endif } @@ -736,7 +710,6 @@ void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d) int MacroAssembler::insts_for_sethi(address a, bool worst_case) { -#ifdef _LP64 if (worst_case) return 7; intptr_t iaddr = (intptr_t) a; int msb32 = (int) (iaddr >> 32); @@ -756,9 +729,6 @@ int MacroAssembler::insts_for_sethi(address a, bool worst_case) { } } return count; -#else - return 1; -#endif } int MacroAssembler::worst_case_insts_for_set() { @@ -1488,11 +1458,7 @@ void MacroAssembler::calc_mem_param_words(Register Rparam_words, Register Rresul void MacroAssembler::calc_frame_size(Register Rextra_words, Register Rresult) { -#ifdef _LP64 add(Rextra_words, frame::memory_parameter_word_sp_offset, Rresult); -#else - add(Rextra_words, frame::memory_parameter_word_sp_offset + 1, Rresult); -#endif bclr(1, Rresult); sll(Rresult, LogBytesPerWord, Rresult); // Rresult has total frame bytes } @@ -1531,22 +1497,12 @@ void MacroAssembler::cmp_zero_and_br(Condition c, Register s1, Label& L, bool a, // Does a test & branch on 32-bit systems and a register-branch on 64-bit. void MacroAssembler::br_null( Register s1, bool a, Predict p, Label& L ) { assert_not_delayed(); -#ifdef _LP64 bpr( rc_z, a, p, s1, L ); -#else - tst(s1); - br ( zero, a, p, L ); -#endif } void MacroAssembler::br_notnull( Register s1, bool a, Predict p, Label& L ) { assert_not_delayed(); -#ifdef _LP64 bpr( rc_nz, a, p, s1, L ); -#else - tst(s1); - br ( notZero, a, p, L ); -#endif } // Compare registers and branch with nop in delay slot or cbcond without delay slot. @@ -1862,14 +1818,12 @@ void MacroAssembler::lushr( Register Rin_high, Register Rin_low, bind( done ); } -#ifdef _LP64 void MacroAssembler::lcmp( Register Ra, Register Rb, Register Rresult) { cmp(Ra, Rb); mov(-1, Rresult); movcc(equal, false, xcc, 0, Rresult); movcc(greater, false, xcc, 1, Rresult); } -#endif void MacroAssembler::load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed) { @@ -2668,9 +2622,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, // if compare/exchange succeeded we found an unlocked object and we now have locked it // hence we are done cmp(Rmark, Rscratch); -#ifdef _LP64 sub(Rscratch, STACK_BIAS, Rscratch); -#endif brx(Assembler::equal, false, Assembler::pt, done); delayed()->sub(Rscratch, SP, Rscratch); //pull next instruction into delay slot @@ -2716,9 +2668,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, // Stack-lock attempt failed - check for recursive stack-lock. // See the comments below about how we might remove this case. -#ifdef _LP64 sub(Rscratch, STACK_BIAS, Rscratch); -#endif assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); andcc(Rscratch, 0xfffff003, Rscratch); br(Assembler::always, false, Assembler::pt, done); @@ -2800,9 +2750,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, // control to the "slow" operators in synchronizer.cpp. // RScratch contains the fetched obj->mark value from the failed CAS. -#ifdef _LP64 sub(Rscratch, STACK_BIAS, Rscratch); -#endif sub(Rscratch, SP, Rscratch); assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); andcc(Rscratch, 0xfffff003, Rscratch); @@ -3720,11 +3668,7 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { Label not_already_dirty, restart, refill, young_card; -#ifdef _LP64 __ srlx(O0, CardTableModRefBS::card_shift, O0); -#else - __ srl(O0, CardTableModRefBS::card_shift, O0); -#endif AddressLiteral addrlit(byte_map_base); __ set(addrlit, O1); // O1 := __ ldub(O0, O1, O2); // O2 := [O0 + O1] @@ -3826,11 +3770,7 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val if (G1RSBarrierRegionFilter) { xor3(store_addr, new_val, tmp); -#ifdef _LP64 srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); -#else - srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); -#endif // XXX Should I predict this taken or not? Does it matter? cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp index a401859e774..afd574a4b9a 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -156,7 +156,6 @@ REGISTER_DECLARATION(Register, O5_savedSP , O5); REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply // a copy SP, so in 64-bit it's a biased value. The bias // is added and removed as needed in the frame code. -REGISTER_DECLARATION(Register, IdispatchTables , I4); // Base address of the bytecode dispatch tables REGISTER_DECLARATION(Register, IdispatchAddress , I3); // Register which saves the dispatch address for each bytecode REGISTER_DECLARATION(Register, ImethodDataPtr , I2); // Pointer to the current method data @@ -228,7 +227,6 @@ REGISTER_DECLARATION(Register, Oissuing_pc , O1); // where the exception is comi #define O5_savedSP AS_REGISTER(Register, O5_savedSP) #define IdispatchAddress AS_REGISTER(Register, IdispatchAddress) #define ImethodDataPtr AS_REGISTER(Register, ImethodDataPtr) -#define IdispatchTables AS_REGISTER(Register, IdispatchTables) #define Oexception AS_REGISTER(Register, Oexception) #define Oissuing_pc AS_REGISTER(Register, Oissuing_pc) @@ -333,14 +331,12 @@ class AddressLiteral VALUE_OBJ_CLASS_SPEC { return external_word_Relocation::spec(addr); case relocInfo::internal_word_type: return internal_word_Relocation::spec(addr); -#ifdef _LP64 case relocInfo::opt_virtual_call_type: return opt_virtual_call_Relocation::spec(); case relocInfo::static_call_type: return static_call_Relocation::spec(); case relocInfo::runtime_call_type: return runtime_call_Relocation::spec(); -#endif case relocInfo::none: return RelocationHolder(); default: @@ -396,12 +392,10 @@ class AddressLiteral VALUE_OBJ_CLASS_SPEC { : _address((address) addr), _rspec(rspec_from_rtype(rtype, (address) addr)) {} -#ifdef _LP64 // 32-bit complains about a multiple declaration for int*. AddressLiteral(intptr_t* addr, relocInfo::relocType rtype = relocInfo::none) : _address((address) addr), _rspec(rspec_from_rtype(rtype, (address) addr)) {} -#endif AddressLiteral(Metadata* addr, relocInfo::relocType rtype = relocInfo::none) : _address((address) addr), @@ -464,16 +458,10 @@ class Argument VALUE_OBJ_CLASS_SPEC { bool _is_in; public: -#ifdef _LP64 enum { n_register_parameters = 6, // only 6 registers may contain integer parameters n_float_register_parameters = 16 // Can have up to 16 floating registers }; -#else - enum { - n_register_parameters = 6 // only 6 registers may contain integer parameters - }; -#endif // creation Argument(int number, bool is_in) : _number(number), _is_in(is_in) {} @@ -489,7 +477,6 @@ class Argument VALUE_OBJ_CLASS_SPEC { // locating register-based arguments: bool is_register() const { return _number < n_register_parameters; } -#ifdef _LP64 // locating Floating Point register-based arguments: bool is_float_register() const { return _number < n_float_register_parameters; } @@ -501,7 +488,6 @@ class Argument VALUE_OBJ_CLASS_SPEC { assert(is_float_register(), "must be a register argument"); return as_FloatRegister(( number() *2 )); } -#endif Register as_register() const { assert(is_register(), "must be a register argument"); @@ -604,15 +590,15 @@ class MacroAssembler : public Assembler { bool check_exception=true // flag which indicates if exception should be checked ); + public: + MacroAssembler(CodeBuffer* code) : Assembler(code) {} + // This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code. // The implementation is only non-empty for the InterpreterMacroAssembler, // as only the interpreter handles and ForceEarlyReturn PopFrame requests. virtual void check_and_handle_popframe(Register scratch_reg); virtual void check_and_handle_earlyret(Register scratch_reg); - public: - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - // Support for NULL-checks // // Generates code that causes a NULL OS exception if the content of reg is NULL. @@ -1217,9 +1203,7 @@ public: void lushr( Register Rin_high, Register Rin_low, Register Rcount, Register Rout_high, Register Rout_low, Register Rtemp ); -#ifdef _LP64 void lcmp( Register Ra, Register Rb, Register Rresult); -#endif // Load and store values by size and signed-ness void load_sized_value( Address src, Register dst, size_t size_in_bytes, bool is_signed); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp index 2f1c949bb7f..f92bcc1efaf 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -45,19 +45,11 @@ inline void MacroAssembler::pd_patch_instruction(address branch, address target) // Use the right loads/stores for the platform inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, s2, d); -#else - ld( s1, s2, d); -#endif } inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, simm13a, d); -#else - ld( s1, simm13a, d); -#endif } #ifdef ASSERT @@ -68,35 +60,19 @@ inline void MacroAssembler::ld_ptr( Register s1, ByteSize simm13a, Register d ) #endif inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) { -#ifdef _LP64 ldx(s1, s2, d); -#else - ld( s1, s2, d); -#endif } inline void MacroAssembler::ld_ptr(const Address& a, Register d, int offset) { -#ifdef _LP64 ldx(a, d, offset); -#else - ld( a, d, offset); -#endif } inline void MacroAssembler::st_ptr( Register d, Register s1, Register s2 ) { -#ifdef _LP64 Assembler::stx(d, s1, s2); -#else - st( d, s1, s2); -#endif } inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) { -#ifdef _LP64 Assembler::stx(d, s1, simm13a); -#else - st( d, s1, simm13a); -#endif } #ifdef ASSERT @@ -107,84 +83,44 @@ inline void MacroAssembler::st_ptr( Register d, Register s1, ByteSize simm13a ) #endif inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) { -#ifdef _LP64 stx(d, s1, s2); -#else - st( d, s1, s2); -#endif } inline void MacroAssembler::st_ptr(Register d, const Address& a, int offset) { -#ifdef _LP64 stx(d, a, offset); -#else - st( d, a, offset); -#endif } // Use the right loads/stores for the platform inline void MacroAssembler::ld_long( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, s2, d); -#else - Assembler::ldd(s1, s2, d); -#endif } inline void MacroAssembler::ld_long( Register s1, int simm13a, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, simm13a, d); -#else - Assembler::ldd(s1, simm13a, d); -#endif } inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) { -#ifdef _LP64 ldx(s1, s2, d); -#else - ldd(s1, s2, d); -#endif } inline void MacroAssembler::ld_long(const Address& a, Register d, int offset) { -#ifdef _LP64 ldx(a, d, offset); -#else - ldd(a, d, offset); -#endif } inline void MacroAssembler::st_long( Register d, Register s1, Register s2 ) { -#ifdef _LP64 Assembler::stx(d, s1, s2); -#else - Assembler::std(d, s1, s2); -#endif } inline void MacroAssembler::st_long( Register d, Register s1, int simm13a ) { -#ifdef _LP64 Assembler::stx(d, s1, simm13a); -#else - Assembler::std(d, s1, simm13a); -#endif } inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) { -#ifdef _LP64 stx(d, s1, s2); -#else - std(d, s1, s2); -#endif } inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) { -#ifdef _LP64 stx(d, a, offset); -#else - std(d, a, offset); -#endif } inline void MacroAssembler::stbool(Register d, const Address& a) { stb(d, a); } @@ -207,45 +143,25 @@ inline void MacroAssembler::casx( Register s1, Register s2, Register d) { casxa( // Functions for isolating 64 bit atomic swaps for LP64 // cas_ptr will perform cas for 32 bit VM's and casx for 64 bit VM's inline void MacroAssembler::cas_ptr( Register s1, Register s2, Register d) { -#ifdef _LP64 casx( s1, s2, d ); -#else - cas( s1, s2, d ); -#endif } // Functions for isolating 64 bit shifts for LP64 inline void MacroAssembler::sll_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::sllx(s1, s2, d); -#else - Assembler::sll( s1, s2, d); -#endif } inline void MacroAssembler::sll_ptr( Register s1, int imm6a, Register d ) { -#ifdef _LP64 Assembler::sllx(s1, imm6a, d); -#else - Assembler::sll( s1, imm6a, d); -#endif } inline void MacroAssembler::srl_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::srlx(s1, s2, d); -#else - Assembler::srl( s1, s2, d); -#endif } inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) { -#ifdef _LP64 Assembler::srlx(s1, imm6a, d); -#else - Assembler::srl( s1, imm6a, d); -#endif } inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { @@ -277,11 +193,7 @@ inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { // Branch that tests either xcc or icc depending on the // architecture compiled (LP64 or not) inline void MacroAssembler::brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { -#ifdef _LP64 Assembler::bp(c, a, xcc, p, d, rt); -#else - MacroAssembler::br(c, a, p, d, rt); -#endif } inline void MacroAssembler::brx( Condition c, bool a, Predict p, Label& L ) { @@ -338,7 +250,6 @@ inline void MacroAssembler::call( address d, relocInfo::relocType rt ) { } inline void MacroAssembler::call( address d, RelocationHolder const& rspec ) { -#ifdef _LP64 intptr_t disp; // NULL is ok because it will be relocated later. // Must change NULL to a reachable address in order to @@ -355,9 +266,6 @@ inline void MacroAssembler::call( address d, RelocationHolder const& rspec ) { } else { Assembler::call(d, rspec); } -#else - Assembler::call( d, rspec ); -#endif } inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { @@ -414,12 +322,7 @@ inline void MacroAssembler::cmp( Register s1, int simm13a ) { subcc( s1, simm13 // 2 instructions. All PCs in the CodeCache are within 2 Gig of each other. inline intptr_t MacroAssembler::load_pc_address( Register reg, int bytes_to_skip ) { intptr_t thepc = (intptr_t)pc() + 2*BytesPerInstWord + bytes_to_skip; -#ifdef _LP64 Unimplemented(); -#else - Assembler::sethi( thepc & ~0x3ff, reg, internal_word_Relocation::spec((address)thepc)); - add(reg, thepc & 0x3ff, reg, internal_word_Relocation::spec((address)thepc)); -#endif return thepc; } @@ -554,7 +457,6 @@ inline void MacroAssembler::store_ptr_argument( Register s, Argument& a ) { } -#ifdef _LP64 inline void MacroAssembler::store_float_argument( FloatRegister s, Argument& a ) { if (a.is_float_register()) // V9 ABI has F1, F3, F5 are used to pass instead of O0, O1, O2 @@ -579,7 +481,6 @@ inline void MacroAssembler::store_long_argument( Register s, Argument& a ) { else stx(s, a.as_address()); } -#endif inline void MacroAssembler::round_to( Register r, int modulus ) { assert_not_delayed(); @@ -640,22 +541,13 @@ inline void MacroAssembler::clrx( Register s1, int simm13a) { stx( G0, s1, simm1 inline void MacroAssembler::clruw( Register s, Register d ) { srl( s, G0, d); } inline void MacroAssembler::clruwu( Register d ) { srl( d, G0, d); } -#ifdef _LP64 // Make all 32 bit loads signed so 64 bit registers maintain proper sign inline void MacroAssembler::ld( Register s1, Register s2, Register d) { ldsw( s1, s2, d); } inline void MacroAssembler::ld( Register s1, int simm13a, Register d) { ldsw( s1, simm13a, d); } -#else -inline void MacroAssembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2, d); } -inline void MacroAssembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } -#endif #ifdef ASSERT // ByteSize is only a class when ASSERT is defined, otherwise it's an int. -# ifdef _LP64 inline void MacroAssembler::ld(Register s1, ByteSize simm13a, Register d) { ldsw( s1, in_bytes(simm13a), d); } -# else -inline void MacroAssembler::ld(Register s1, ByteSize simm13a, Register d) { lduw( s1, in_bytes(simm13a), d); } -# endif #endif inline void MacroAssembler::ld( const Address& a, Register d, int offset) { diff --git a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp deleted file mode 100644 index cc0141c283e..00000000000 --- a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2004, 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. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - __ save(SP, -256, SP); - int offset = (i << 8) + j; - Register src = G0; - if (!Assembler::is_simm13(offset)) { - __ sethi(offset, L0); - src = L0; - offset = offset & ((1 << 10) - 1); - } - __ brx(Assembler::always, false, Assembler::pt, common_code); - - // Load L0 with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[13..8] (6 bits) which virtual method table? - __ delayed()->or3(src, offset, L0); - } - } - - __ bind(common_code); - - // Expecting to be called with the "this" pointer in O0/I0 (where - // "this" is a Klass object). In addition, L0 was set (above) to - // identify the method and table. - - // Look up the correct vtable pointer. - - __ set((intptr_t)vtbl_list, L2); // L2 = address of new vtable list. - __ srl(L0, 8, L3); // Isolate L3 = vtable identifier. - __ sll(L3, LogBytesPerWord, L3); - __ ld_ptr(L2, L3, L3); // L3 = new (correct) vtable pointer. - __ st_ptr(L3, Address(I0, 0)); // Save correct vtable ptr in entry. - - // Restore registers and jump to the correct method; - - __ and3(L0, 255, L4); // Isolate L3 = method offset;. - __ sll(L4, LogBytesPerWord, L4); - __ ld_ptr(L3, L4, L4); // Get address of correct virtual method - __ jmpl(L4, 0, G0); // Jump to correct method. - __ delayed()->restore(); // Restore registers. - - __ flush(); - *mc_top = (char*)__ pc(); - - guarantee(*mc_top <= mc_end, "Insufficient space for method wrappers."); -} diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index f93dbf17212..b863ea92908 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -71,7 +71,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register temp_reg, Register temp2_reg, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); bool did_save = false; if (temp_reg == noreg || temp2_reg == noreg) { temp_reg = L1; @@ -181,8 +181,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), method_temp); __ verify_oop(method_temp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ ld_ptr( Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())), method_temp); + __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), method_temp); + __ verify_oop(method_temp); + __ ld_ptr( Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())), method_temp); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -332,7 +333,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method( G5_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -384,14 +386,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2); } - __ ld_ptr(member_vmtarget, G5_method); + __ load_heap_oop(member_vmtarget, G5_method); + __ ld_ptr(vmtarget_method, G5_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2); } - __ ld_ptr(member_vmtarget, G5_method); + __ load_heap_oop(member_vmtarget, G5_method); + __ ld_ptr(vmtarget_method, G5_method); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp index 103c712cee4..950619dacb4 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -236,8 +236,6 @@ void NativeCall::test() { //------------------------------------------------------------------- -#ifdef _LP64 - void NativeFarCall::set_destination(address dest) { // Address materialized in the instruction stream, so nothing to do. return; @@ -290,8 +288,6 @@ void NativeFarCall::test() { } // End code for unit testing implementation of NativeFarCall class -#endif // _LP64 - //------------------------------------------------------------------- @@ -304,18 +300,9 @@ void NativeMovConstReg::verify() { // verify the pattern "sethi %hi22(imm), reg ; add reg, %lo10(imm), reg" Register rd = inv_rd(i0); -#ifndef _LP64 - if (!(is_op2(i0, Assembler::sethi_op2) && rd != G0 && - is_op3(i1, Assembler::add_op3, Assembler::arith_op) && - inv_immed(i1) && (unsigned)get_simm13(i1) < (1 << 10) && - rd == inv_rs1(i1) && rd == inv_rd(i1))) { - fatal("not a set_metadata"); - } -#else if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) { fatal("not a set_metadata"); } -#endif } @@ -324,23 +311,13 @@ void NativeMovConstReg::print() { } -#ifdef _LP64 intptr_t NativeMovConstReg::data() const { return data64(addr_at(sethi_offset), long_at(add_offset)); } -#else -intptr_t NativeMovConstReg::data() const { - return data32(long_at(sethi_offset), long_at(add_offset)); -} -#endif void NativeMovConstReg::set_data(intptr_t x) { -#ifdef _LP64 set_data64_sethi(addr_at(sethi_offset), x); -#else - set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), x)); -#endif set_long_at(add_offset, set_data32_simm13( long_at(add_offset), x)); // also store the value into an oop_Relocation cell, if any @@ -508,20 +485,12 @@ void NativeMovConstRegPatching::print() { int NativeMovConstRegPatching::data() const { -#ifdef _LP64 return data64(addr_at(sethi_offset), long_at(add_offset)); -#else - return data32(long_at(sethi_offset), long_at(add_offset)); -#endif } void NativeMovConstRegPatching::set_data(int x) { -#ifdef _LP64 set_data64_sethi(addr_at(sethi_offset), x); -#else - set_long_at(sethi_offset, set_data32_sethi(long_at(sethi_offset), x)); -#endif set_long_at(add_offset, set_data32_simm13(long_at(add_offset), x)); // also store the value into an oop_Relocation cell, if any @@ -758,21 +727,12 @@ void NativeJump::verify() { assert((int)jmpl_offset == (int)NativeMovConstReg::add_offset, "sethi size ok"); // verify the pattern "sethi %hi22(imm), treg ; jmpl treg, %lo10(imm), lreg" Register rd = inv_rd(i0); -#ifndef _LP64 - if (!(is_op2(i0, Assembler::sethi_op2) && rd != G0 && - (is_op3(i1, Assembler::jmpl_op3, Assembler::arith_op)) && - inv_immed(i1) && (unsigned)get_simm13(i1) < (1 << 10) && - rd == inv_rs1(i1))) { - fatal("not a jump_to instruction"); - } -#else // In LP64, the jump instruction location varies for non relocatable // jumps, for example is could be sethi, xor, jmp instead of the // 7 instructions for sethi. So let's check sethi only. if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) { fatal("not a jump_to instruction"); } -#endif } diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index d0582f34265..2649ea48d80 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -121,11 +121,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { bool is_safepoint_poll() { int x = long_at(0); -#ifdef _LP64 return is_op3(x, Assembler::ldx_op3, Assembler::ldst_op) && -#else - return is_op3(x, Assembler::lduw_op3, Assembler::ldst_op) && -#endif (inv_rd(x) == G0) && (inv_immed(x) ? Assembler::inv_simm13(x) == 0 : inv_rs2(x) == G0); } @@ -432,22 +428,6 @@ class NativeCallReg: public NativeInstruction { // instructions in the sparcv9 vm. Used to call native methods which may be loaded // anywhere in the address space, possibly out of reach of a call instruction. -#ifndef _LP64 - -// On 32-bit systems, a far call is the same as a near one. -class NativeFarCall; -inline NativeFarCall* nativeFarCall_at(address instr); -class NativeFarCall : public NativeCall { -public: - friend inline NativeFarCall* nativeFarCall_at(address instr) { return (NativeFarCall*)nativeCall_at(instr); } - friend NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) - { return (NativeFarCall*)nativeCall_overwriting_at(instr, destination); } - friend NativeFarCall* nativeFarCall_before(address return_address) - { return (NativeFarCall*)nativeCall_before(return_address); } -}; - -#else - // The format of this extended-range call is: // jumpl_to addr, lreg // == sethi %hi54(addr), O7 ; jumpl O7, %lo10(addr), O7 ; @@ -515,7 +495,6 @@ class NativeFarCall: public NativeInstruction { static void replace_mt_safe(address instr_addr, address code_buffer); }; -#endif // _LP64 // An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions // (used to manipulate inlined data references, etc.) @@ -567,13 +546,8 @@ class NativeMovConstReg: public NativeInstruction { public: enum Sparc_specific_constants { sethi_offset = 0, -#ifdef _LP64 add_offset = 7 * BytesPerInstWord, instruction_size = 8 * BytesPerInstWord -#else - add_offset = 4, - instruction_size = 8 -#endif }; address instruction_address() const { return addr_at(0); } @@ -626,11 +600,7 @@ inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address); public: enum Sparc_specific_constants { sethi_offset = 0, -#ifdef _LP64 nop_offset = 7 * BytesPerInstWord, -#else - nop_offset = sethi_offset + BytesPerInstWord, -#endif add_offset = nop_offset + BytesPerInstWord, instruction_size = add_offset + BytesPerInstWord }; @@ -705,11 +675,7 @@ class NativeMovRegMem: public NativeInstruction { offset_width = 13, sethi_offset = 0, -#ifdef _LP64 add_offset = 7 * BytesPerInstWord, -#else - add_offset = 4, -#endif ldst_offset = add_offset + BytesPerInstWord }; bool is_immediate() const { @@ -720,11 +686,7 @@ class NativeMovRegMem: public NativeInstruction { address instruction_address() const { return addr_at(0); } address next_instruction_address() const { -#ifdef _LP64 return addr_at(is_immediate() ? 4 : (7 * BytesPerInstWord)); -#else - return addr_at(is_immediate() ? 4 : 12); -#endif } intptr_t offset() const { return is_immediate()? inv_simm(long_at(0), offset_width) : @@ -777,19 +739,13 @@ class NativeJump: public NativeInstruction { public: enum Sparc_specific_constants { sethi_offset = 0, -#ifdef _LP64 jmpl_offset = 7 * BytesPerInstWord, instruction_size = 9 * BytesPerInstWord // includes delay slot -#else - jmpl_offset = 1 * BytesPerInstWord, - instruction_size = 3 * BytesPerInstWord // includes delay slot -#endif }; address instruction_address() const { return addr_at(0); } address next_instruction_address() const { return addr_at(instruction_size); } -#ifdef _LP64 address jump_destination() const { return (address) data64(instruction_address(), long_at(jmpl_offset)); } @@ -797,15 +753,6 @@ class NativeJump: public NativeInstruction { set_data64_sethi( instruction_address(), (intptr_t)dest); set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); } -#else - address jump_destination() const { - return (address) data32(long_at(sethi_offset), long_at(jmpl_offset)); - } - void set_jump_destination(address dest) { - set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), (intptr_t)dest)); - set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); - } -#endif // Creation friend inline NativeJump* nativeJump_at(address address) { diff --git a/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp b/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp index 8fd22e24670..98cfb72c405 100644 --- a/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp @@ -166,7 +166,6 @@ REGISTER_DEFINITION(Register, I5_savedSP); REGISTER_DEFINITION(Register, O5_savedSP); REGISTER_DEFINITION(Register, IdispatchAddress); REGISTER_DEFINITION(Register, ImethodDataPtr); -REGISTER_DEFINITION(Register, IdispatchTables); REGISTER_DEFINITION(Register, Lmethod); REGISTER_DEFINITION(Register, Llocals); REGISTER_DEFINITION(Register, Oexception); diff --git a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp index 9c70bd0ef4d..f75588c8538 100644 --- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -93,7 +93,6 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { case Assembler::branch_op: { -#ifdef _LP64 jint inst2; guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi"); if (format() != 0) { @@ -121,17 +120,6 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { } else { ip->set_data64_sethi( ip->addr_at(0), (intptr_t)x ); } -#else - guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi"); - inst &= ~Assembler::hi22( -1); - inst |= Assembler::hi22((intptr_t)x); - // (ignore offset; it doesn't play into the sethi) - if (verify_only) { - guarantee(ip->long_at(0) == inst, "instructions must match"); - } else { - ip->set_long_at(0, inst); - } -#endif } break; diff --git a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp index a2d3b2c3928..26daae3757b 100644 --- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -34,12 +34,8 @@ // There is no need for format bits; the instructions are // sufficiently self-identifying. -#ifndef _LP64 - format_width = 0 -#else // Except narrow oops in 64-bits VM. format_width = 1 -#endif }; diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index 613e662d65c..9c8f76ca42c 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -127,56 +127,10 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // OopMap* map = new OopMap(*total_frame_words, 0); OopMap* map = new OopMap(frame_size_in_slots, 0); -#if !defined(_LP64) - - // Save 64-bit O registers; they will get their heads chopped off on a 'save'. - __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); - __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); - __ stx(O2, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8); - __ stx(O3, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8); - __ stx(O4, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8); - __ stx(O5, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8); -#endif /* _LP64 */ - __ save(SP, -frame_size, SP); -#ifndef _LP64 - // Reload the 64 bit Oregs. Although they are now Iregs we load them - // to Oregs here to avoid interrupts cutting off their heads - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8, O2); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8, O3); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8, O4); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8, O5); - - __ stx(O0, SP, o0_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o0_offset + 4)>>2), O0->as_VMReg()); - - __ stx(O1, SP, o1_offset+STACK_BIAS); - - map->set_callee_saved(VMRegImpl::stack2reg((o1_offset + 4)>>2), O1->as_VMReg()); - - __ stx(O2, SP, o2_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o2_offset + 4)>>2), O2->as_VMReg()); - - __ stx(O3, SP, o3_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o3_offset + 4)>>2), O3->as_VMReg()); - - __ stx(O4, SP, o4_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o4_offset + 4)>>2), O4->as_VMReg()); - - __ stx(O5, SP, o5_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o5_offset + 4)>>2), O5->as_VMReg()); -#endif /* _LP64 */ - - -#ifdef _LP64 int debug_offset = 0; -#else - int debug_offset = 4; -#endif // Save the G's __ stx(G1, SP, g1_offset+STACK_BIAS); map->set_callee_saved(VMRegImpl::stack2reg((g1_offset + debug_offset)>>2), G1->as_VMReg()); @@ -192,18 +146,6 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // This is really a waste but we'll keep things as they were for now if (true) { -#ifndef _LP64 - map->set_callee_saved(VMRegImpl::stack2reg((o0_offset)>>2), O0->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o1_offset)>>2), O1->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o2_offset)>>2), O2->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o3_offset)>>2), O3->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o4_offset)>>2), O4->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o5_offset)>>2), O5->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g1_offset)>>2), G1->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g3_offset)>>2), G3->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g4_offset)>>2), G4->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g5_offset)>>2), G5->as_VMReg()->next()); -#endif /* _LP64 */ } @@ -250,70 +192,22 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) { __ ldx(SP, g4_offset+STACK_BIAS, G4); __ ldx(SP, g5_offset+STACK_BIAS, G5); - -#if !defined(_LP64) - // Restore the 64-bit O's. - __ ldx(SP, o0_offset+STACK_BIAS, O0); - __ ldx(SP, o1_offset+STACK_BIAS, O1); - __ ldx(SP, o2_offset+STACK_BIAS, O2); - __ ldx(SP, o3_offset+STACK_BIAS, O3); - __ ldx(SP, o4_offset+STACK_BIAS, O4); - __ ldx(SP, o5_offset+STACK_BIAS, O5); - - // And temporarily place them in TLS - - __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); - __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); - __ stx(O2, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8); - __ stx(O3, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8); - __ stx(O4, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8); - __ stx(O5, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8); -#endif /* _LP64 */ - // Restore flags __ ldxfsr(SP, fsr_offset+STACK_BIAS); __ restore(); -#if !defined(_LP64) - // Now reload the 64bit Oregs after we've restore the window. - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8, O2); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8, O3); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8, O4); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8, O5); -#endif /* _LP64 */ - } // Pop the current frame and restore the registers that might be holding // a result. void RegisterSaver::restore_result_registers(MacroAssembler* masm) { -#if !defined(_LP64) - // 32bit build returns longs in G1 - __ ldx(SP, g1_offset+STACK_BIAS, G1); - - // Retrieve the 64-bit O's. - __ ldx(SP, o0_offset+STACK_BIAS, O0); - __ ldx(SP, o1_offset+STACK_BIAS, O1); - // and save to TLS - __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); - __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); -#endif /* _LP64 */ - __ ldf(FloatRegisterImpl::D, SP, d00_offset+STACK_BIAS, as_FloatRegister(0)); __ restore(); -#if !defined(_LP64) - // Now reload the 64bit Oregs after we've restore the window. - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); -#endif /* _LP64 */ - } // Is vector's size (in bytes) bigger than a size saved by default? @@ -410,11 +304,6 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, case T_CHAR: case T_BYTE: case T_BOOLEAN: -#ifndef _LP64 - case T_OBJECT: - case T_ARRAY: - case T_ADDRESS: // Used, e.g., in slow-path locking for the lock's stack address -#endif // _LP64 if (int_reg < int_reg_max) { Register r = is_outgoing ? as_oRegister(int_reg++) : as_iRegister(int_reg++); regs[i].set1(r->as_VMReg()); @@ -423,7 +312,6 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, } break; -#ifdef _LP64 case T_LONG: assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting VOID in other half"); // fall-through @@ -439,16 +327,6 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, slot += 2; } break; -#else - case T_LONG: - assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting VOID in other half"); - // On 32-bit SPARC put longs always on the stack to keep the pressure off - // integer argument registers. They should be used for oops. - slot = round_to(slot, 2); // align - regs[i].set2(VMRegImpl::stack2reg(slot)); - slot += 2; -#endif - break; case T_FLOAT: if (flt_reg < flt_reg_max) { @@ -554,7 +432,6 @@ void AdapterGenerator::patch_callers_callsite() { // The longs must go to the stack by hand since in the 32 bit build they can be trashed by window ops. -#ifdef _LP64 // mov(s,d) __ mov(G1, L1); __ mov(G4, L4); @@ -571,20 +448,6 @@ void AdapterGenerator::patch_callers_callsite() { __ mov(L1, G1); __ mov(L4, G4); __ mov(L5, G5_method); -#else - __ stx(G1, FP, -8 + STACK_BIAS); - __ stx(G4, FP, -16 + STACK_BIAS); - __ mov(G5_method, L5); - __ mov(G5_method, O0); // VM needs target method - __ mov(I7, O1); // VM needs caller's callsite - // Must be a leaf call... - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite), relocInfo::runtime_call_type); - __ delayed()->mov(G2_thread, L7_thread_cache); - __ mov(L7_thread_cache, G2_thread); - __ ldx(FP, -8 + STACK_BIAS, G1); - __ ldx(FP, -16 + STACK_BIAS, G4); - __ mov(L5, G5_method); -#endif /* _LP64 */ __ restore(); // Restore args __ bind(L); @@ -605,28 +468,9 @@ RegisterOrConstant AdapterGenerator::next_arg_slot(const int st_off) { // Stores long into offset pointed to by base void AdapterGenerator::store_c2i_long(Register r, Register base, const int st_off, bool is_stack) { -#ifdef _LP64 // In V9, longs are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. __ stx(r, base, next_arg_slot(st_off)); -#else -#ifdef COMPILER2 - // Misaligned store of 64-bit data - __ stw(r, base, arg_slot(st_off)); // lo bits - __ srlx(r, 32, r); - __ stw(r, base, next_arg_slot(st_off)); // hi bits -#else - if (is_stack) { - // Misaligned store of 64-bit data - __ stw(r, base, arg_slot(st_off)); // lo bits - __ srlx(r, 32, r); - __ stw(r, base, next_arg_slot(st_off)); // hi bits - } else { - __ stw(r->successor(), base, arg_slot(st_off) ); // lo bits - __ stw(r , base, next_arg_slot(st_off)); // hi bits - } -#endif // COMPILER2 -#endif // _LP64 } void AdapterGenerator::store_c2i_object(Register r, Register base, @@ -642,15 +486,9 @@ void AdapterGenerator::store_c2i_int(Register r, Register base, // Stores into offset pointed to by base void AdapterGenerator::store_c2i_double(VMReg r_2, VMReg r_1, Register base, const int st_off) { -#ifdef _LP64 // In V9, doubles are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. __ stf(FloatRegisterImpl::D, r_1->as_FloatRegister(), base, next_arg_slot(st_off)); -#else - // Need to marshal 64-bit value from misaligned Lesp loads - __ stf(FloatRegisterImpl::S, r_1->as_FloatRegister(), base, next_arg_slot(st_off)); - __ stf(FloatRegisterImpl::S, r_2->as_FloatRegister(), base, arg_slot(st_off) ); -#endif } void AdapterGenerator::store_c2i_float(FloatRegister f, Register base, @@ -957,22 +795,17 @@ void AdapterGenerator::gen_i2c_adapter(int total_args_passed, if (!r_2->is_valid()) { __ ld(Gargs, arg_slot(ld_off), r); } else { -#ifdef _LP64 // In V9, longs are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. RegisterOrConstant slot = (sig_bt[i] == T_LONG) ? next_arg_slot(ld_off) : arg_slot(ld_off); __ ldx(Gargs, slot, r); -#else - fatal("longs should be on stack"); -#endif } } else { assert(r_1->is_FloatRegister(), ""); if (!r_2->is_valid()) { __ ldf(FloatRegisterImpl::S, Gargs, arg_slot(ld_off), r_1->as_FloatRegister()); } else { -#ifdef _LP64 // In V9, doubles are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. This code also handles longs that // are passed on the stack, but need a stack-to-stack move through a @@ -980,11 +813,6 @@ void AdapterGenerator::gen_i2c_adapter(int total_args_passed, RegisterOrConstant slot = (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) ? next_arg_slot(ld_off) : arg_slot(ld_off); __ ldf(FloatRegisterImpl::D, Gargs, slot, r_1->as_FloatRegister()); -#else - // Need to marshal 64-bit value from misaligned Lesp loads - __ ldf(FloatRegisterImpl::S, Gargs, next_arg_slot(ld_off), r_1->as_FloatRegister()); - __ ldf(FloatRegisterImpl::S, Gargs, arg_slot(ld_off), r_2->as_FloatRegister()); -#endif } } // Was the argument really intended to be on the stack, but was loaded @@ -1157,7 +985,6 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, // See int_stk_helper for a further discussion. int max_stack_slots = (frame::varargs_offset * VMRegImpl::slots_per_word) - SharedRuntime::out_preserve_stack_slots(); -#ifdef _LP64 // V9 convention: All things "as-if" on double-wide stack slots. // Hoist any int/ptr/long's in the first 6 to int regs. // Hoist any flt/dbl's in the first 16 dbl regs. @@ -1241,44 +1068,6 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, if (off > max_stack_slots) max_stack_slots = off; } } - -#else // _LP64 - // V8 convention: first 6 things in O-regs, rest on stack. - // Alignment is willy-nilly. - for (int i = 0; i < total_args_passed; i++) { - switch (sig_bt[i]) { - case T_ADDRESS: // raw pointers, like current thread, for VM calls - case T_ARRAY: - case T_BOOLEAN: - case T_BYTE: - case T_CHAR: - case T_FLOAT: - case T_INT: - case T_OBJECT: - case T_METADATA: - case T_SHORT: - regs[i].set1(int_stk_helper(i)); - break; - case T_DOUBLE: - case T_LONG: - assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half"); - regs[i].set_pair(int_stk_helper(i + 1), int_stk_helper(i)); - break; - case T_VOID: regs[i].set_bad(); break; - default: - ShouldNotReachHere(); - } - if (regs[i].first()->is_stack()) { - int off = regs[i].first()->reg2stack(); - if (off > max_stack_slots) max_stack_slots = off; - } - if (regs[i].second()->is_stack()) { - int off = regs[i].second()->reg2stack(); - if (off > max_stack_slots) max_stack_slots = off; - } - } -#endif // _LP64 - return round_to(max_stack_slots + 1, 2); } @@ -1406,12 +1195,7 @@ static void object_move(MacroAssembler* masm, Register rHandle = dst.first()->is_stack() ? L5 : dst.first()->as_Register(); __ add(FP, reg2offset(src.first()) + STACK_BIAS, rHandle); __ ld_ptr(rHandle, 0, L4); -#ifdef _LP64 __ movr( Assembler::rc_z, L4, G0, rHandle ); -#else - __ tst( L4 ); - __ movcc( Assembler::zero, false, Assembler::icc, G0, rHandle ); -#endif if (dst.first()->is_stack()) { __ st_ptr(rHandle, SP, reg2offset(dst.first()) + STACK_BIAS); } @@ -1432,12 +1216,7 @@ static void object_move(MacroAssembler* masm, } map->set_oop(VMRegImpl::stack2reg(oop_slot)); __ add(SP, offset + STACK_BIAS, rHandle); -#ifdef _LP64 __ movr( Assembler::rc_z, rOop, G0, rHandle ); -#else - __ tst( rOop ); - __ movcc( Assembler::zero, false, Assembler::icc, G0, rHandle ); -#endif if (dst.first()->is_stack()) { __ st_ptr(rHandle, SP, reg2offset(dst.first()) + STACK_BIAS); @@ -2068,11 +1847,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ delayed()->or3(mask, markOopDesc::hash_mask & 0x3ff, mask); // Check for a valid (non-zero) hash code and get its value. -#ifdef _LP64 __ srlx(header, markOopDesc::hash_shift, hash); -#else - __ srl(header, markOopDesc::hash_shift, hash); -#endif __ andcc(hash, mask, hash); __ br(Assembler::equal, false, Assembler::pn, slowCase); __ delayed()->nop(); @@ -2408,7 +2183,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // We have all of the arguments setup at this point. We MUST NOT touch any Oregs // except O6/O7. So if we must call out we must push a new frame. We immediately // push a new frame and flush the windows. -#ifdef _LP64 intptr_t thepc = (intptr_t) __ pc(); { address here = __ pc(); @@ -2416,9 +2190,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ call(here + 8, relocInfo::none); __ delayed()->nop(); } -#else - intptr_t thepc = __ load_pc_address(O7, 0); -#endif /* _LP64 */ // We use the same pc/oopMap repeatedly when we call out oop_maps->add_gc_map(thepc - start, map); @@ -2553,13 +2324,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Transition from _thread_in_Java to _thread_in_native. __ set(_thread_in_native, G3_scratch); -#ifdef _LP64 AddressLiteral dest(native_func); __ relocate(relocInfo::runtime_call_type); __ jumpl_to(dest, O7, O7); -#else - __ call(native_func, relocInfo::runtime_call_type); -#endif __ delayed()->st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); __ restore_thread(L7_thread_cache); // restore G2_thread @@ -2574,9 +2341,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, case T_DOUBLE: break; // Got it where we want it (unless slow-path) // In 64 bits build result is in O0, in O0, O1 in 32bit build case T_LONG: -#ifndef _LP64 - __ mov(O1, I1); -#endif // Fall thru case T_OBJECT: // Really a handle case T_ARRAY: @@ -2797,16 +2561,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Return -#ifndef _LP64 - if (ret_type == T_LONG) { - - // Must leave proper result in O0,O1 and G1 (c2/tiered only) - __ sllx(I0, 32, G1); // Shift bits into high G1 - __ srl (I1, 0, I1); // Zero extend O1 (harmless?) - __ or3 (I1, G1, G1); // OR 64 bits into G1 - } -#endif - __ ret(); __ delayed()->restore(); @@ -2868,10 +2622,6 @@ static void gen_new_frame(MacroAssembler* masm, bool deopt) { #ifdef ASSERT // make sure that the frames are aligned properly -#ifndef _LP64 - __ btst(wordSize*2-1, SP); - __ breakpoint_trap(Assembler::notZero, Assembler::ptr_cc); -#endif #endif // Deopt needs to pass some extra live values from frame to frame @@ -2989,13 +2739,7 @@ void SharedRuntime::generate_deopt_blob() { pad += 1000; // Increase the buffer size when compiling for JVMCI } #endif -#ifdef _LP64 CodeBuffer buffer("deopt_blob", 2100+pad, 512); -#else - // Measured 8/7/03 at 1212 in 32bit debug build (no VerifyThread) - // Measured 8/7/03 at 1396 in 32bit debug build (VerifyThread) - CodeBuffer buffer("deopt_blob", 1600+pad, 512); -#endif /* _LP64 */ MacroAssembler* masm = new MacroAssembler(&buffer); FloatRegister Freturn0 = F0; Register Greturn1 = G1; @@ -3006,9 +2750,6 @@ void SharedRuntime::generate_deopt_blob() { Register G4deopt_mode = G4_scratch; int frame_size_words; Address saved_Freturn0_addr(FP, -sizeof(double) + STACK_BIAS); -#if !defined(_LP64) && defined(COMPILER2) - Address saved_Greturn1_addr(FP, -sizeof(double) -sizeof(jlong) + STACK_BIAS); -#endif Label cont; OopMapSet *oop_maps = new OopMapSet(); @@ -3220,30 +2961,13 @@ void SharedRuntime::generate_deopt_blob() { // to the interpreter entry point __ save(SP, -frame_size_words*wordSize, SP); __ stf(FloatRegisterImpl::D, Freturn0, saved_Freturn0_addr); -#if !defined(_LP64) -#if defined(COMPILER2) - // 32-bit 1-register longs return longs in G1 - __ stx(Greturn1, saved_Greturn1_addr); -#endif - __ set_last_Java_frame(SP, noreg); - __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4deopt_mode); -#else // LP64 uses g4 in set_last_Java_frame __ mov(G4deopt_mode, O1); __ set_last_Java_frame(SP, G0); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, O1); -#endif __ reset_last_Java_frame(); __ ldf(FloatRegisterImpl::D, saved_Freturn0_addr, Freturn0); -#if !defined(_LP64) && defined(COMPILER2) - // In 32 bit, C2 returns longs in G1 so restore the saved G1 into - // I0/I1 if the return value is long. - Label not_long; - __ cmp_and_br_short(O0,T_LONG, Assembler::notEqual, Assembler::pt, not_long); - __ ldd(saved_Greturn1_addr,I0); - __ bind(not_long); -#endif __ ret(); __ delayed()->restore(); @@ -3273,13 +2997,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { pad += (JavaThread::stack_shadow_zone_size() / os::vm_page_size())*16 + 32; } #endif -#ifdef _LP64 CodeBuffer buffer("uncommon_trap_blob", 2700+pad, 512); -#else - // Measured 8/7/03 at 660 in 32bit debug build (no VerifyThread) - // Measured 8/7/03 at 1028 in 32bit debug build (VerifyThread) - CodeBuffer buffer("uncommon_trap_blob", 2000+pad, 512); -#endif MacroAssembler* masm = new MacroAssembler(&buffer); Register O2UnrollBlock = O2; Register O2klass_index = O2; diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index fa0bedae739..f6c5367c634 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1998, 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 @@ -311,7 +311,6 @@ reg_class o7_regI(R_O7); // ---------------------------- // Pointer Register Classes // ---------------------------- -#ifdef _LP64 // 64-bit build means 64-bit pointers means hi/lo pairs reg_class ptr_reg( R_G1H,R_G1, R_G3H,R_G3, R_G4H,R_G4, R_G5H,R_G5, R_O0H,R_O0, R_O1H,R_O1, R_O2H,R_O2, R_O3H,R_O3, R_O4H,R_O4, R_O5H,R_O5, @@ -344,40 +343,6 @@ reg_class o1_regP(R_O1H,R_O1); reg_class o2_regP(R_O2H,R_O2); reg_class o7_regP(R_O7H,R_O7); -#else // _LP64 -// 32-bit build means 32-bit pointers means 1 register. -reg_class ptr_reg( R_G1, R_G3,R_G4,R_G5, - R_O0,R_O1,R_O2,R_O3,R_O4,R_O5, - R_L0,R_L1,R_L2,R_L3,R_L4,R_L5,R_L6,R_L7, - R_I0,R_I1,R_I2,R_I3,R_I4,R_I5); -// Lock encodings use G3 and G4 internally -reg_class lock_ptr_reg(R_G1, R_G5, - R_O0,R_O1,R_O2,R_O3,R_O4,R_O5, - R_L0,R_L1,R_L2,R_L3,R_L4,R_L5,R_L6,R_L7, - R_I0,R_I1,R_I2,R_I3,R_I4,R_I5); -// Special class for storeP instructions, which can store SP or RPC to TLS. -// It is also used for memory addressing, allowing direct TLS addressing. -reg_class sp_ptr_reg( R_G1,R_G2,R_G3,R_G4,R_G5, - R_O0,R_O1,R_O2,R_O3,R_O4,R_O5,R_SP, - R_L0,R_L1,R_L2,R_L3,R_L4,R_L5,R_L6,R_L7, - R_I0,R_I1,R_I2,R_I3,R_I4,R_I5,R_FP); -// R_L7 is the lowest-priority callee-save (i.e., NS) register -// We use it to save R_G2 across calls out of Java. -reg_class l7_regP(R_L7); - -// Other special pointer regs -reg_class g1_regP(R_G1); -reg_class g2_regP(R_G2); -reg_class g3_regP(R_G3); -reg_class g4_regP(R_G4); -reg_class g5_regP(R_G5); -reg_class i0_regP(R_I0); -reg_class o0_regP(R_O0); -reg_class o1_regP(R_O1); -reg_class o2_regP(R_O2); -reg_class o7_regP(R_O7); -#endif // _LP64 - // ---------------------------- // Long Register Classes @@ -386,12 +351,9 @@ reg_class o7_regP(R_O7); // Note: O7 is never in this class; it is sometimes used as an encoding temp. reg_class long_reg( R_G1H,R_G1, R_G3H,R_G3, R_G4H,R_G4, R_G5H,R_G5 ,R_O0H,R_O0, R_O1H,R_O1, R_O2H,R_O2, R_O3H,R_O3, R_O4H,R_O4, R_O5H,R_O5 -#ifdef _LP64 // 64-bit, longs in 1 register: use all 64-bit integer registers -// 32-bit, longs in 1 register: cannot use I's and L's. Restrict to O's and G's. ,R_L0H,R_L0, R_L1H,R_L1, R_L2H,R_L2, R_L3H,R_L3, R_L4H,R_L4, R_L5H,R_L5, R_L6H,R_L6, R_L7H,R_L7 ,R_I0H,R_I0, R_I1H,R_I1, R_I2H,R_I2, R_I3H,R_I3, R_I4H,R_I4, R_I5H,R_I5 -#endif // _LP64 ); reg_class g1_regL(R_G1H,R_G1); @@ -533,10 +495,8 @@ static Register reg_to_register_object(int register_encoding); // instructions which either zero-fill or sign-fill). bool can_branch_register( Node *bol, Node *cmp ) { if( !BranchOnRegister ) return false; -#ifdef _LP64 if( cmp->Opcode() == Op_CmpP ) return true; // No problems with pointer compares -#endif if( cmp->Opcode() == Op_CmpL ) return true; // No problems with long compares @@ -617,15 +577,11 @@ int MachCallDynamicJavaNode::ret_addr_offset() { } int MachCallRuntimeNode::ret_addr_offset() { -#ifdef _LP64 if (MacroAssembler::is_far_target(entry_point())) { return NativeFarCall::instruction_size; } else { return NativeCall::instruction_size; } -#else - return NativeCall::instruction_size; // call; delay slot -#endif } // Indicate if the safepoint node needs the polling page as an input. @@ -1024,7 +980,6 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, RelocationHolder co #ifdef ASSERT if (preserve_g2 && (VerifyCompiledCode || VerifyOops)) { -#ifdef _LP64 // Trash argument dump slots. __ set(0xb0b8ac0db0b8ac0d, G1); __ mov(G1, G5); @@ -1034,22 +989,6 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, RelocationHolder co __ stx(G1, SP, STACK_BIAS + 0x98); __ stx(G1, SP, STACK_BIAS + 0xA0); __ stx(G1, SP, STACK_BIAS + 0xA8); -#else // _LP64 - // this is also a native call, so smash the first 7 stack locations, - // and the various registers - - // Note: [SP+0x40] is sp[callee_aggregate_return_pointer_sp_offset], - // while [SP+0x44..0x58] are the argument dump slots. - __ set((intptr_t)0xbaadf00d, G1); - __ mov(G1, G5); - __ sllx(G1, 32, G1); - __ or3(G1, G5, G1); - __ mov(G1, G5); - __ stx(G1, SP, 0x40); - __ stx(G1, SP, 0x48); - __ stx(G1, SP, 0x50); - __ stw(G1, SP, 0x58); // Do not trash [SP+0x5C] which is a usable spill slot -#endif // _LP64 } #endif /*ASSERT*/ } @@ -1262,11 +1201,7 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { if(do_polling() && ra_->C->is_method_compilation()) { st->print("SETHI #PollAddr,L0\t! Load Polling address\n\t"); -#ifdef _LP64 st->print("LDX [L0],G0\t!Poll for Safepointing\n\t"); -#else - st->print("LDUW [L0],G0\t!Poll for Safepointing\n\t"); -#endif } if(do_polling()) { @@ -1472,75 +1407,10 @@ static void mach_spill_copy_implementation_helper(const MachNode* mach, // hardware does the flop for me. Doubles are always aligned, so no problem // there. Misaligned sources only come from native-long-returns (handled // special below). -#ifndef _LP64 - if (src_first_rc == rc_int && // source is already big-endian - src_second_rc != rc_bad && // 64-bit move - ((dst_first & 1) != 0 || dst_second != dst_first + 1)) { // misaligned dst - assert((src_first & 1) == 0 && src_second == src_first + 1, "source must be aligned"); - // Do the big-endian flop. - OptoReg::Name tmp = dst_first ; dst_first = dst_second ; dst_second = tmp ; - enum RC tmp_rc = dst_first_rc; dst_first_rc = dst_second_rc; dst_second_rc = tmp_rc; - } -#endif // -------------------------------------- // Check for integer reg-reg copy if (src_first_rc == rc_int && dst_first_rc == rc_int) { -#ifndef _LP64 - if (src_first == R_O0_num && src_second == R_O1_num) { // Check for the evil O0/O1 native long-return case - // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value - // as stored in memory. On a big-endian machine like SPARC, this means that the _second - // operand contains the least significant word of the 64-bit value and vice versa. - OptoReg::Name tmp = OptoReg::Name(R_O7_num); - assert((dst_first & 1) == 0 && dst_second == dst_first + 1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); - // Shift O0 left in-place, zero-extend O1, then OR them into the dst - if ( cbuf ) { - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020); - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000); - emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second]); -#ifndef PRODUCT - } else { - print_helper(st, "SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); - print_helper(st, "SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); - print_helper(st, "OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); -#endif - } - return; - } else if (dst_first == R_I0_num && dst_second == R_I1_num) { - // returning a long value in I0/I1 - // a SpillCopy must be able to target a return instruction's reg_class - // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value - // as stored in memory. On a big-endian machine like SPARC, this means that the _second - // operand contains the least significant word of the 64-bit value and vice versa. - OptoReg::Name tdest = dst_first; - - if (src_first == dst_first) { - tdest = OptoReg::Name(R_O7_num); - } - - if (cbuf) { - assert((src_first & 1) == 0 && (src_first + 1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); - // Shift value in upper 32-bits of src to lower 32-bits of I0; move lower 32-bits to I1 - // ShrL_reg_imm6 - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000); - // ShrR_reg_imm6 src, 0, dst - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000); - if (tdest != dst_first) { - emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest]); - } - } -#ifndef PRODUCT - else { - print_helper(st, "SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); - print_helper(st, "SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); - if (tdest != dst_first) { - print_helper(st, "MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); - } - } -#endif // PRODUCT - return size+8; - } -#endif // !_LP64 // Else normal reg-reg copy assert(src_second != dst_first, "smashed second before evacuating it"); impl_mov_helper(cbuf, src_first, dst_first, Assembler::or_op3, 0, "MOV ", st); @@ -1614,58 +1484,6 @@ static void mach_spill_copy_implementation_helper(const MachNode* mach, } assert(src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad"); -#ifndef _LP64 - // In the LP64 build, all registers can be moved as aligned/adjacent - // pairs, so there's never any need to move the high bits separately. - // The 32-bit builds have to deal with the 32-bit ABI which can force - // all sorts of silly alignment problems. - - // Check for integer reg-reg copy. Hi bits are stuck up in the top - // 32-bits of a 64-bit register, but are needed in low bits of another - // register (else it's a hi-bits-to-hi-bits copy which should have - // happened already as part of a 64-bit move) - if (src_second_rc == rc_int && dst_second_rc == rc_int) { - assert((src_second & 1) == 1, "its the evil O0/O1 native return case"); - assert((dst_second & 1) == 0, "should have moved with 1 64-bit move"); - // Shift src_second down to dst_second's low bits. - if (cbuf) { - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); -#ifndef PRODUCT - } else { - print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second - 1), OptoReg::regname(dst_second)); -#endif - } - return; - } - - // Check for high word integer store. Must down-shift the hi bits - // into a temp register, then fall into the case of storing int bits. - if (src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second & 1) == 1) { - // Shift src_second down to dst_second's low bits. - if (cbuf) { - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); -#ifndef PRODUCT - } else { - print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second-1), OptoReg::regname(R_O7_num)); -#endif - } - src_second = OptoReg::Name(R_O7_num); // Not R_O7H_num! - } - - // Check for high word integer load - if (dst_second_rc == rc_int && src_second_rc == rc_stack) - return impl_helper(this, cbuf, ra_, true, ra_->reg2offset(src_second), dst_second, Assembler::lduw_op3, "LDUW", size, st); - - // Check for high word integer store - if (src_second_rc == rc_int && dst_second_rc == rc_stack) - return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stw_op3, "STW ", size, st); - - // Check for high word float store - if (src_second_rc == rc_float && dst_second_rc == rc_stack) - return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stf_op3, "STF ", size, st); - -#endif // !_LP64 - Unimplemented(); } @@ -1743,7 +1561,6 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const { #ifndef PRODUCT void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { st->print_cr("\nUEP:"); -#ifdef _LP64 if (UseCompressedClassPointers) { assert(Universe::heap() != NULL, "java heap should be initialized"); st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); @@ -1762,11 +1579,6 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { } st->print_cr("\tCMP R_G5,R_G3" ); st->print ("\tTne xcc,R_G0+ST_RESERVED_FOR_USER_0+2"); -#else // _LP64 - st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); - st->print_cr("\tCMP R_G5,R_G3" ); - st->print ("\tTne icc,R_G0+ST_RESERVED_FOR_USER_0+2"); -#endif // _LP64 } #endif @@ -1874,9 +1686,7 @@ const bool Matcher::match_rule_supported(int opcode) { if (!UsePopCountInstruction) return false; case Op_CompareAndSwapL: -#ifdef _LP64 case Op_CompareAndSwapP: -#endif if (!VM_Version::supports_cx8()) return false; break; @@ -1919,12 +1729,12 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize == 8, ""); return Op_RegD; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { fatal("vector shift is not supported"); return Node::NotAMachineReg; } @@ -1992,13 +1802,11 @@ const bool Matcher::require_postalloc_expand = false; const bool Matcher::need_masked_shift_count = false; bool Matcher::narrow_oop_use_complex_address() { - NOT_LP64(ShouldNotCallThis()); assert(UseCompressedOops, "only for compressed oops code"); return false; } bool Matcher::narrow_klass_use_complex_address() { - NOT_LP64(ShouldNotCallThis()); assert(UseCompressedClassPointers, "only for compressed klass code"); return false; } @@ -2027,11 +1835,7 @@ const bool Matcher::rematerialize_float_constants = false; // needed. Else we split the double into 2 integer pieces and move it // piece-by-piece. Only happens when passing doubles into C code as the // Java calling convention forces doubles to be aligned. -#ifdef _LP64 const bool Matcher::misaligned_doubles_ok = true; -#else -const bool Matcher::misaligned_doubles_ok = false; -#endif // No-op on SPARC. void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { @@ -2050,11 +1854,7 @@ bool Matcher::float_in_double() { return false; } // The relevant question is how the int is callee-saved. In _LP64 // the whole long is written but de-opt'ing will have to extract // the relevant 32 bits, in not-_LP64 only the low 32 bits is written. -#ifdef _LP64 const bool Matcher::int_in_long = true; -#else -const bool Matcher::int_in_long = false; -#endif // Return whether or not this register is ever used as an argument. This // function is used on startup to build the trampoline stubs in generateOptoStub. @@ -2068,7 +1868,6 @@ bool Matcher::can_be_java_arg( int reg ) { reg == R_I3_num || reg == R_I4_num || reg == R_I5_num ) return true; -#ifdef _LP64 // 64-bit builds can pass 64-bit pointers and longs in // the high I registers if( reg == R_I0H_num || @@ -2082,14 +1881,6 @@ bool Matcher::can_be_java_arg( int reg ) { return true; } -#else - // 32-bit builds with longs-in-one-entry pass longs in G1 & G4. - // Longs cannot be passed in O regs, because O regs become I regs - // after a 'save' and I regs get their high bits chopped off on - // interrupt. - if( reg == R_G1H_num || reg == R_G1_num ) return true; - if( reg == R_G4H_num || reg == R_G4_num ) return true; -#endif // A few float args in registers if( reg >= R_F0_num && reg <= R_F7_num ) return true; @@ -2152,19 +1943,11 @@ void Compile::reshape_address(AddPNode* addp) { // The intptr_t operand types, defined by textual substitution. // (Cf. opto/type.hpp. This lets us avoid many, many other ifdefs.) -#ifdef _LP64 #define immX immL #define immX13 immL13 #define immX13m7 immL13m7 #define iRegX iRegL #define g1RegX g1RegL -#else -#define immX immI -#define immX13 immI13 -#define immX13m7 immI13m7 -#define iRegX iRegI -#define g1RegX g1RegI -#endif //----------ENCODING BLOCK----------------------------------------------------- // This block specifies the encoding classes used by the compiler to output @@ -2326,7 +2109,6 @@ encode %{ emit3_simm13( cbuf, Assembler::arith_op, R_O1_enc, Assembler::add_op3, R_O7_enc, frame::pc_return_offset ); %} -#ifdef _LP64 /* %%% merge with enc_to_bool */ enc_class enc_convP2B( iRegI dst, iRegP src ) %{ MacroAssembler _masm(&cbuf); @@ -2335,7 +2117,6 @@ encode %{ Register dst_reg = reg_to_register_object($dst$$reg); __ movr(Assembler::rc_nz, src_reg, 1, dst_reg); %} -#endif enc_class enc_cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, iRegI tmp ) %{ // (Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))) @@ -2626,16 +2407,6 @@ encode %{ // to G1 so the register allocator will not have to deal with the misaligned register // pair. enc_class adjust_long_from_native_call %{ -#ifndef _LP64 - if (returns_long()) { - // sllx O0,32,O0 - emit3_simm13( cbuf, Assembler::arith_op, R_O0_enc, Assembler::sllx_op3, R_O0_enc, 0x1020 ); - // srl O1,0,O1 - emit3_simm13( cbuf, Assembler::arith_op, R_O1_enc, Assembler::srl_op3, R_O1_enc, 0x0000 ); - // or O0,O1,G1 - emit3 ( cbuf, Assembler::arith_op, R_G1_enc, Assembler:: or_op3, R_O0_enc, 0, R_O1_enc ); - } -#endif %} enc_class Java_To_Runtime (method meth) %{ // CALL Java_To_Runtime @@ -3102,11 +2873,7 @@ frame %{ cisc_spilling_operand_name(indOffset); // Number of stack slots consumed by a Monitor enter -#ifdef _LP64 sync_stack_slots(2); -#else - sync_stack_slots(1); -#endif // Compiled code's Frame Pointer frame_pointer(R_SP); @@ -3124,13 +2891,8 @@ frame %{ // Number of outgoing stack slots killed above the out_preserve_stack_slots // for calls to C. Supports the var-args backing area for register parms. // ADLC doesn't support parsing expressions, so I folded the math by hand. -#ifdef _LP64 // (callee_register_argument_save_area_words (6) + callee_aggregate_return_pointer_words (0)) * 2-stack-slots-per-word varargs_C_out_slots_killed(12); -#else - // (callee_register_argument_save_area_words (6) + callee_aggregate_return_pointer_words (1)) * 1-stack-slots-per-word - varargs_C_out_slots_killed( 7); -#endif // The after-PROLOG location of the return address. Location of // return address specifies a type (REG or STACK) and a number @@ -3161,17 +2923,10 @@ frame %{ // opcodes. This simplifies the register allocator. c_return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); -#ifdef _LP64 static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; -#else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; -#endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); %} @@ -3179,17 +2934,10 @@ frame %{ // Location of compiled Java return values. Same as C return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); -#ifdef _LP64 static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; -#else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; -#endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); %} @@ -3444,7 +3192,6 @@ operand immP() %{ interface(CONST_INTER); %} -#ifdef _LP64 // Pointer Immediate: 64-bit operand immP_set() %{ predicate(!VM_Version::is_niagara_plus()); @@ -3478,7 +3225,6 @@ operand immP_no_oop_cheap() %{ format %{ %} interface(CONST_INTER); %} -#endif operand immP13() %{ predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095)); @@ -3919,11 +3665,7 @@ operand flagsRegP() %{ constraint(ALLOC_IN_RC(int_flags)); match(RegFlags); -#ifdef _LP64 format %{ "xcc_P" %} -#else - format %{ "icc_P" %} -#endif interface(REG_INTER); %} @@ -4500,7 +4242,6 @@ pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) MS : R(2); %} -#ifdef _LP64 pipe_class ialu_clr_and_mover( iRegI dst, iRegP src ) %{ instruction_count(1); multiple_bundles; dst : C(write)+1; @@ -4509,7 +4250,6 @@ pipe_class ialu_clr_and_mover( iRegI dst, iRegP src ) %{ BR : E(2); MS : E(2); %} -#endif // Integer ALU reg operation pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{ @@ -4614,13 +4354,8 @@ pipe_class loadConP( iRegP dst, immP src ) %{ // Polling Address pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{ -#ifdef _LP64 instruction_count(0); multiple_bundles; fixed_latency(6); -#else - dst : E(write); - IALU : R; -#endif %} // Long Constant small @@ -5361,7 +5096,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{ ins_pipe(istore_mem_reg); %} -#ifdef _LP64 // Load pointer from stack slot, 64-bit encoding instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ match(Set dst src); @@ -5381,27 +5115,6 @@ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} -#else // _LP64 -// Load pointer from stack slot, 32-bit encoding -instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ - match(Set dst src); - ins_cost(MEMORY_REF_COST); - format %{ "LDUW $src,$dst\t!ptr" %} - opcode(Assembler::lduw_op3, Assembler::ldst_op); - ins_encode(simple_form3_mem_reg( src, dst ) ); - ins_pipe(iload_mem); -%} - -// Store pointer to stack slot -instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ - match(Set dst src); - ins_cost(MEMORY_REF_COST); - format %{ "STW $src,$dst\t!ptr" %} - opcode(Assembler::stw_op3, Assembler::ldst_op); - ins_encode(simple_form3_mem_reg( dst, src ) ); - ins_pipe(istore_mem_reg); -%} -#endif // _LP64 //------------Special Nop instructions for bundling - no match rules----------- // Nop using the A0 functional unit @@ -5858,17 +5571,10 @@ instruct loadP(iRegP dst, memory mem) %{ ins_cost(MEMORY_REF_COST); size(4); -#ifndef _LP64 - format %{ "LDUW $mem,$dst\t! ptr" %} - ins_encode %{ - __ lduw($mem$$Address, $dst$$Register); - %} -#else format %{ "LDX $mem,$dst\t! ptr" %} ins_encode %{ __ ldx($mem$$Address, $dst$$Register); %} -#endif ins_pipe(iload_mem); %} @@ -5891,17 +5597,10 @@ instruct loadKlass(iRegP dst, memory mem) %{ ins_cost(MEMORY_REF_COST); size(4); -#ifndef _LP64 - format %{ "LDUW $mem,$dst\t! klass ptr" %} - ins_encode %{ - __ lduw($mem$$Address, $dst$$Register); - %} -#else format %{ "LDX $mem,$dst\t! klass ptr" %} ins_encode %{ __ ldx($mem$$Address, $dst$$Register); %} -#endif ins_pipe(iload_mem); %} @@ -5969,26 +5668,6 @@ instruct loadConI13( iRegI dst, immI13 src ) %{ ins_pipe(ialu_imm); %} -#ifndef _LP64 -instruct loadConP(iRegP dst, immP con) %{ - match(Set dst con); - ins_cost(DEFAULT_COST * 3/2); - format %{ "SET $con,$dst\t!ptr" %} - ins_encode %{ - relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc(); - intptr_t val = $con$$constant; - if (constant_reloc == relocInfo::oop_type) { - __ set_oop_constant((jobject) val, $dst$$Register); - } else if (constant_reloc == relocInfo::metadata_type) { - __ set_metadata_constant((Metadata*)val, $dst$$Register); - } else { // non-oop pointers, e.g. card mark base, heap top - assert(constant_reloc == relocInfo::none, "unexpected reloc type"); - __ set(val, $dst$$Register); - } - %} - ins_pipe(loadConP); -%} -#else instruct loadConP_set(iRegP dst, immP_set con) %{ match(Set dst con); ins_cost(DEFAULT_COST * 3/2); @@ -6032,7 +5711,6 @@ instruct loadConP_no_oop_cheap(iRegP dst, immP_no_oop_cheap con) %{ %} ins_pipe(loadConP); %} -#endif // _LP64 instruct loadConP0(iRegP dst, immP0 src) %{ match(Set dst src); @@ -6186,19 +5864,6 @@ instruct prefetchAlloc_bis( iRegP dst ) %{ %} // Next code is used for finding next cache line address to prefetch. -#ifndef _LP64 -instruct cacheLineAdr( iRegP dst, iRegP src, immI13 mask ) %{ - match(Set dst (CastX2P (AndI (CastP2X src) mask))); - ins_cost(DEFAULT_COST); - size(4); - - format %{ "AND $src,$mask,$dst\t! next cache line address" %} - ins_encode %{ - __ and3($src$$Register, $mask$$constant, $dst$$Register); - %} - ins_pipe(ialu_reg_imm); -%} -#else instruct cacheLineAdr( iRegP dst, iRegP src, immL13 mask ) %{ match(Set dst (CastX2P (AndL (CastP2X src) mask))); ins_cost(DEFAULT_COST); @@ -6210,7 +5875,6 @@ instruct cacheLineAdr( iRegP dst, iRegP src, immL13 mask ) %{ %} ins_pipe(ialu_reg_imm); %} -#endif //----------Store Instructions------------------------------------------------- // Store Byte @@ -6322,13 +5986,8 @@ instruct storeP(memory dst, sp_ptr_RegP src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); -#ifndef _LP64 - format %{ "STW $src,$dst\t! ptr" %} - opcode(Assembler::stw_op3, 0, REGP_OP); -#else format %{ "STX $src,$dst\t! ptr" %} opcode(Assembler::stx_op3, 0, REGP_OP); -#endif ins_encode( form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_spORreg); %} @@ -6337,13 +5996,8 @@ instruct storeP0(memory dst, immP0 src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); -#ifndef _LP64 - format %{ "STW $src,$dst\t! ptr" %} - opcode(Assembler::stw_op3, 0, REGP_OP); -#else format %{ "STX $src,$dst\t! ptr" %} opcode(Assembler::stx_op3, 0, REGP_OP); -#endif ins_encode( form3_mem_reg( dst, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -7094,13 +6748,8 @@ instruct loadPLocked(iRegP dst, memory mem) %{ match(Set dst (LoadPLocked mem)); ins_cost(MEMORY_REF_COST); -#ifndef _LP64 - format %{ "LDUW $mem,$dst\t! ptr" %} - opcode(Assembler::lduw_op3, 0, REGP_OP); -#else format %{ "LDX $mem,$dst\t! ptr" %} opcode(Assembler::ldx_op3, 0, REGP_OP); -#endif ins_encode( form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -7171,9 +6820,7 @@ instruct compareAndSwapI_bool(iRegP mem_ptr, iRegI oldval, iRegI newval, iRegI r %} instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{ -#ifdef _LP64 predicate(VM_Version::supports_cx8()); -#endif match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval))); match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval))); effect( USE mem_ptr, KILL ccr, KILL tmp1); @@ -7184,13 +6831,8 @@ instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI r "MOV 1,$res\n\t" "MOVne xcc,R_G0,$res" %} -#ifdef _LP64 ins_encode( enc_casx(mem_ptr, oldval, newval), enc_lflags_ne_to_boolean(res) ); -#else - ins_encode( enc_casi(mem_ptr, oldval, newval), - enc_iflags_ne_to_boolean(res) ); -#endif ins_pipe( long_memory_op ); %} @@ -7268,17 +6910,6 @@ instruct xchgI( memory mem, iRegI newval) %{ ins_pipe( long_memory_op ); %} -#ifndef _LP64 -instruct xchgP( memory mem, iRegP newval) %{ - match(Set newval (GetAndSetP mem newval)); - format %{ "SWAP [$mem],$newval" %} - size(4); - ins_encode %{ - __ swap($mem$$Address, $newval$$Register); - %} - ins_pipe( long_memory_op ); -%} -#endif instruct xchgN( memory mem, iRegN newval) %{ match(Set newval (GetAndSetN mem newval)); @@ -7740,7 +7371,6 @@ instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ %} // Register Shift Right Immediate with a CastP2X -#ifdef _LP64 instruct shrP_reg_imm6(iRegL dst, iRegP src1, immU6 src2) %{ match(Set dst (URShiftL (CastP2X src1) src2)); size(4); @@ -7749,16 +7379,6 @@ instruct shrP_reg_imm6(iRegL dst, iRegP src1, immU6 src2) %{ ins_encode( form3_sd_rs1_imm6_rd( src1, src2, dst ) ); ins_pipe(ialu_reg_imm); %} -#else -instruct shrP_reg_imm5(iRegI dst, iRegP src1, immU5 src2) %{ - match(Set dst (URShiftI (CastP2X src1) src2)); - size(4); - format %{ "SRL $src1,$src2,$dst\t! Cast ptr $src1 to int and shift" %} - opcode(Assembler::srl_op3, Assembler::arith_op); - ins_encode( form3_rs1_imm5_rd( src1, src2, dst ) ); - ins_pipe(ialu_reg_imm); -%} -#endif //----------Floating Point Arithmetic Instructions----------------------------- @@ -8001,21 +7621,6 @@ instruct orL_reg_imm13(iRegL dst, iRegL src1, immL13 con) %{ ins_pipe(ialu_reg_imm); %} -#ifndef _LP64 - -// Use sp_ptr_RegP to match G2 (TLS register) without spilling. -instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ - match(Set dst (OrI src1 (CastP2X src2))); - - size(4); - format %{ "OR $src1,$src2,$dst" %} - opcode(Assembler::or_op3, Assembler::arith_op); - ins_encode( form3_rs1_rs2_rd( src1, src2, dst ) ); - ins_pipe(ialu_reg_reg); -%} - -#else - instruct orL_reg_castP2X(iRegL dst, iRegL src1, sp_ptr_RegP src2) %{ match(Set dst (OrL src1 (CastP2X src2))); @@ -8027,8 +7632,6 @@ instruct orL_reg_castP2X(iRegL dst, iRegL src1, sp_ptr_RegP src2) %{ ins_pipe(ialu_reg_reg); %} -#endif - // Xor Instructions // Register Xor instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ @@ -8088,17 +7691,6 @@ instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{ ins_pipe(ialu_reg_ialu); %} -#ifndef _LP64 -instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{ - match(Set dst (Conv2B src)); - effect( KILL ccr ); - ins_cost(DEFAULT_COST*2); - format %{ "CMP R_G0,$src\n\t" - "ADDX R_G0,0,$dst" %} - ins_encode( enc_to_bool( src, dst ) ); - ins_pipe(ialu_reg_ialu); -%} -#else instruct convP2B( iRegI dst, iRegP src ) %{ match(Set dst (Conv2B src)); ins_cost(DEFAULT_COST*2); @@ -8107,7 +7699,6 @@ instruct convP2B( iRegI dst, iRegP src ) %{ ins_encode( form3_g0_rs2_rd_move( src, dst ), enc_convP2B( dst, src ) ); ins_pipe(ialu_clr_and_mover); %} -#endif instruct cmpLTMask0( iRegI dst, iRegI src, immI0 zero, flagsReg ccr ) %{ match(Set dst (CmpLTMask src zero)); @@ -8750,16 +8341,10 @@ instruct convL2F_reg(regF dst, iRegL src) %{ instruct convL2I_reg(iRegI dst, iRegL src) %{ match(Set dst (ConvL2I src)); -#ifndef _LP64 - format %{ "MOV $src.lo,$dst\t! long->int" %} - ins_encode( form3_g0_rs2_rd_move_lo2( src, dst ) ); - ins_pipe(ialu_move_reg_I_to_L); -#else size(4); format %{ "SRA $src,R_G0,$dst\t! long->int" %} ins_encode( form3_rs1_rd_signextend_lo1( src, dst ) ); ins_pipe(ialu_reg); -#endif %} // Register Shift Right Immediate @@ -9528,11 +9113,7 @@ instruct cmpP_reg_branch_short(cmpOpP cmp, iRegP op1, iRegP op2, label labl, fla size(4); ins_cost(BRANCH_COST); -#ifdef _LP64 format %{ "CXB$cmp $op1,$op2,$labl\t! ptr" %} -#else - format %{ "CWB$cmp $op1,$op2,$labl\t! ptr" %} -#endif ins_encode %{ Label* L = $labl$$label; assert(__ use_cbcond(*L), "back to back cbcond"); @@ -9550,11 +9131,7 @@ instruct cmpP_null_branch_short(cmpOpP cmp, iRegP op1, immP0 null, label labl, f size(4); ins_cost(BRANCH_COST); -#ifdef _LP64 format %{ "CXB$cmp $op1,0,$labl\t! ptr" %} -#else - format %{ "CWB$cmp $op1,0,$labl\t! ptr" %} -#endif ins_encode %{ Label* L = $labl$$label; assert(__ use_cbcond(*L), "back to back cbcond"); @@ -9822,11 +9399,7 @@ instruct safePoint_poll(iRegP poll) %{ effect(USE poll); size(4); -#ifdef _LP64 format %{ "LDX [$poll],R_G0\t! Safepoint: poll for GC" %} -#else - format %{ "LDUW [$poll],R_G0\t! Safepoint: poll for GC" %} -#endif ins_encode %{ __ relocate(relocInfo::poll_type); __ ld_ptr($poll$$Register, 0, G0); @@ -10259,15 +9832,15 @@ instruct array_equalsC(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI resul instruct has_negatives(o0RegP pAryR, g3RegI iSizeR, notemp_iRegI resultR, iRegL tmp1L, iRegL tmp2L, iRegL tmp3L, iRegL tmp4L, - flagsReg ccr) + flagsReg ccr) %{ match(Set resultR (HasNegatives pAryR iSizeR)); effect(TEMP resultR, TEMP tmp1L, TEMP tmp2L, TEMP tmp3L, TEMP tmp4L, USE pAryR, USE iSizeR, KILL ccr); format %{ "has negatives byte[] $pAryR,$iSizeR -> $resultR // KILL $tmp1L,$tmp2L,$tmp3L,$tmp4L" %} ins_encode %{ - __ has_negatives($pAryR$$Register, $iSizeR$$Register, + __ has_negatives($pAryR$$Register, $iSizeR$$Register, $resultR$$Register, - $tmp1L$$Register, $tmp2L$$Register, + $tmp1L$$Register, $tmp2L$$Register, $tmp3L$$Register, $tmp4L$$Register); %} ins_pipe(long_memory_op); diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 8babb471137..9c4713e936d 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -216,9 +216,7 @@ class StubGenerator: public StubCodeGenerator { __ ld_ptr(parameter_size.as_in().as_address(), t); // get parameter size (in words) __ sll(t, Interpreter::logStackElementSize, t); // compute number of bytes __ sub(FP, t, Gargs); // setup parameter pointer -#ifdef _LP64 __ add( Gargs, STACK_BIAS, Gargs ); // Account for LP64 stack bias -#endif __ mov(SP, O5_savedSP); @@ -271,27 +269,8 @@ class StubGenerator: public StubCodeGenerator { __ delayed()->stf(FloatRegisterImpl::D, F0, addr, G0); __ BIND(is_long); -#ifdef _LP64 __ ba(exit); __ delayed()->st_long(O0, addr, G0); // store entire long -#else -#if defined(COMPILER2) - // All return values are where we want them, except for Longs. C2 returns - // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. - // Since the interpreter will return longs in G1 and O0/O1 in the 32bit - // build we simply always use G1. - // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to - // do this here. Unfortunately if we did a rethrow we'd see an machepilog node - // first which would move g1 -> O0/O1 and destroy the exception we were throwing. - - __ ba(exit); - __ delayed()->stx(G1, addr, G0); // store entire long -#else - __ st(O1, addr, BytesPerInt); - __ ba(exit); - __ delayed()->st(O0, addr, G0); -#endif /* COMPILER2 */ -#endif /* _LP64 */ } return start; } @@ -746,22 +725,10 @@ class StubGenerator: public StubCodeGenerator { address start = __ pc(); Label miss; -#if defined(COMPILER2) && !defined(_LP64) - // Do not use a 'save' because it blows the 64-bit O registers. - __ add(SP,-4*wordSize,SP); // Make space for 4 temps (stack must be 2 words aligned) - __ st_ptr(L0,SP,(frame::register_save_words+0)*wordSize); - __ st_ptr(L1,SP,(frame::register_save_words+1)*wordSize); - __ st_ptr(L2,SP,(frame::register_save_words+2)*wordSize); - __ st_ptr(L3,SP,(frame::register_save_words+3)*wordSize); - Register Rret = O0; - Register Rsub = O1; - Register Rsuper = O2; -#else __ save_frame(0); Register Rret = I0; Register Rsub = I1; Register Rsuper = I2; -#endif Register L0_ary_len = L0; Register L1_ary_ptr = L1; @@ -775,32 +742,14 @@ class StubGenerator: public StubCodeGenerator { // Match falls through here. __ addcc(G0,0,Rret); // set Z flags, Z result -#if defined(COMPILER2) && !defined(_LP64) - __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0); - __ ld_ptr(SP,(frame::register_save_words+1)*wordSize,L1); - __ ld_ptr(SP,(frame::register_save_words+2)*wordSize,L2); - __ ld_ptr(SP,(frame::register_save_words+3)*wordSize,L3); - __ retl(); // Result in Rret is zero; flags set to Z - __ delayed()->add(SP,4*wordSize,SP); -#else __ ret(); // Result in Rret is zero; flags set to Z __ delayed()->restore(); -#endif __ BIND(miss); __ addcc(G0,1,Rret); // set NZ flags, NZ result -#if defined(COMPILER2) && !defined(_LP64) - __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0); - __ ld_ptr(SP,(frame::register_save_words+1)*wordSize,L1); - __ ld_ptr(SP,(frame::register_save_words+2)*wordSize,L2); - __ ld_ptr(SP,(frame::register_save_words+3)*wordSize,L3); - __ retl(); // Result in Rret is != 0; flags set to NZ - __ delayed()->add(SP,4*wordSize,SP); -#else __ ret(); // Result in Rret is != 0; flags set to NZ __ delayed()->restore(); -#endif return start; } @@ -828,11 +777,11 @@ class StubGenerator: public StubCodeGenerator { // Rtmp - scratch // void assert_clean_int(Register Rint, Register Rtmp) { -#if defined(ASSERT) && defined(_LP64) + #if defined(ASSERT) __ signx(Rint, Rtmp); __ cmp(Rint, Rtmp); __ breakpoint_trap(Assembler::notEqual, Assembler::xcc); -#endif + #endif } // @@ -1019,10 +968,11 @@ class StubGenerator: public StubCodeGenerator { // than prefetch distance. __ set(prefetch_count, O4); __ cmp_and_brx_short(count, O4, Assembler::less, Assembler::pt, L_block_copy); - __ sub(count, prefetch_count, count); + __ sub(count, O4, count); (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy_prefetch, true, true); - __ add(count, prefetch_count, count); // restore count + __ set(prefetch_count, O4); + __ add(count, O4, count); } // prefetch_count > 0 @@ -1043,11 +993,12 @@ class StubGenerator: public StubCodeGenerator { // than prefetch distance. __ set(prefetch_count, O4); __ cmp_and_brx_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_copy); - __ sub(count, prefetch_count, count); + __ sub(count, O4, count); Label L_copy_prefetch; (this->*copy_loop_func)(from, to, count, count_dec, L_copy_prefetch, true, false); - __ add(count, prefetch_count, count); // restore count + __ set(prefetch_count, O4); + __ add(count, O4, count); } // prefetch_count > 0 @@ -1269,17 +1220,6 @@ class StubGenerator: public StubCodeGenerator { // Aligned arrays have 4 bytes alignment in 32-bits VM // and 8 bytes - in 64-bits VM. So we do it only for 32-bits VM // -#ifndef _LP64 - // copy a 4-bytes word if necessary to align 'to' to 8 bytes - __ andcc(to, 7, G0); - __ br(Assembler::zero, false, Assembler::pn, L_skip_alignment); - __ delayed()->ld(from, 0, O3); - __ inc(from, 4); - __ inc(to, 4); - __ dec(count, 4); - __ st(O3, to, -4); - __ BIND(L_skip_alignment); -#endif } else { // copy bytes to align 'to' on 8 byte boundary __ andcc(to, 7, G1); // misaligned bytes @@ -1296,10 +1236,7 @@ class StubGenerator: public StubCodeGenerator { __ delayed()->inc(to); __ BIND(L_skip_alignment); } -#ifdef _LP64 - if (!aligned) -#endif - { + if (!aligned) { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise fall through to the next // code for aligned copy. @@ -1395,15 +1332,12 @@ class StubGenerator: public StubCodeGenerator { __ delayed()->stb(O3, end_to, 0); __ BIND(L_skip_alignment); } -#ifdef _LP64 if (aligned) { // Both arrays are aligned to 8-bytes in 64-bits VM. // The 'count' is decremented in copy_16_bytes_backward_with_shift() // in unaligned case. __ dec(count, 16); - } else -#endif - { + } else { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise jump to the next // code for aligned copy (and substracting 16 from 'count' before jump). @@ -1490,17 +1424,6 @@ class StubGenerator: public StubCodeGenerator { // Aligned arrays have 4 bytes alignment in 32-bits VM // and 8 bytes - in 64-bits VM. // -#ifndef _LP64 - // copy a 2-elements word if necessary to align 'to' to 8 bytes - __ andcc(to, 7, G0); - __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment); - __ delayed()->ld(from, 0, O3); - __ inc(from, 4); - __ inc(to, 4); - __ dec(count, 2); - __ st(O3, to, -4); - __ BIND(L_skip_alignment); -#endif } else { // copy 1 element if necessary to align 'to' on an 4 bytes __ andcc(to, 3, G0); @@ -1524,10 +1447,7 @@ class StubGenerator: public StubCodeGenerator { __ sth(O4, to, -2); __ BIND(L_skip_alignment2); } -#ifdef _LP64 - if (!aligned) -#endif - { + if (!aligned) { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise fall through to the next // code for aligned copy. @@ -1643,20 +1563,16 @@ class StubGenerator: public StubCodeGenerator { __ dec(count, 1 << (shift - 1)); __ BIND(L_skip_align2); } -#ifdef _LP64 if (!aligned) { -#endif - // align to 8 bytes, we know we are 4 byte aligned to start - __ andcc(to, 7, G0); - __ br(Assembler::zero, false, Assembler::pt, L_fill_32_bytes); - __ delayed()->nop(); - __ stw(value, to, 0); - __ inc(to, 4); - __ dec(count, 1 << shift); - __ BIND(L_fill_32_bytes); -#ifdef _LP64 + // align to 8 bytes, we know we are 4 byte aligned to start + __ andcc(to, 7, G0); + __ br(Assembler::zero, false, Assembler::pt, L_fill_32_bytes); + __ delayed()->nop(); + __ stw(value, to, 0); + __ inc(to, 4); + __ dec(count, 1 << shift); + __ BIND(L_fill_32_bytes); } -#endif if (t == T_INT) { // Zero extend value @@ -1857,15 +1773,12 @@ class StubGenerator: public StubCodeGenerator { __ sth(O4, end_to, 0); __ BIND(L_skip_alignment2); } -#ifdef _LP64 if (aligned) { // Both arrays are aligned to 8-bytes in 64-bits VM. // The 'count' is decremented in copy_16_bytes_backward_with_shift() // in unaligned case. __ dec(count, 8); - } else -#endif - { + } else { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise jump to the next // code for aligned copy (and substracting 8 from 'count' before jump). @@ -1974,10 +1887,7 @@ class StubGenerator: public StubCodeGenerator { // Aligned arrays have 4 bytes alignment in 32-bits VM // and 8 bytes - in 64-bits VM. // -#ifdef _LP64 - if (!aligned) -#endif - { + if (!aligned) { // The next check could be put under 'ifndef' since the code in // generate_disjoint_long_copy_core() has own checks and set 'offset'. @@ -2463,16 +2373,12 @@ class StubGenerator: public StubCodeGenerator { __ mov(to, G1); __ mov(count, G5); gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized); - #ifdef _LP64 assert_clean_int(count, O3); // Make sure 'count' is clean int. if (UseCompressedOops) { generate_disjoint_int_copy_core(aligned); } else { generate_disjoint_long_copy_core(aligned); } - #else - generate_disjoint_int_copy_core(aligned); - #endif // O0 is used as temp register gen_write_ref_array_post_barrier(G1, G5, O0); @@ -2518,15 +2424,11 @@ class StubGenerator: public StubCodeGenerator { __ mov(count, G5); gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized); - #ifdef _LP64 if (UseCompressedOops) { generate_conjoint_int_copy_core(aligned); } else { generate_conjoint_long_copy_core(aligned); } - #else - generate_conjoint_int_copy_core(aligned); - #endif // O0 is used as temp register gen_write_ref_array_post_barrier(G1, G5, O0); @@ -3138,7 +3040,6 @@ class StubGenerator: public StubCodeGenerator { "arrayof_jint_disjoint_arraycopy"); StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, entry, &entry_jint_arraycopy, "arrayof_jint_arraycopy"); -#ifdef _LP64 // In 64 bit we need both aligned and unaligned versions of jint arraycopy. // entry_jint_arraycopy always points to the unaligned version (notice that we overwrite it). StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, &entry, @@ -3146,14 +3047,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, entry, &entry_jint_arraycopy, "jint_arraycopy"); -#else - // In 32 bit jints are always HeapWordSize aligned, so always use the aligned version - // (in fact in 32bit we always have a pre-loop part even in the aligned version, - // because it uses 64-bit loads/stores, so the aligned flag is actually ignored). - StubRoutines::_jint_disjoint_arraycopy = StubRoutines::_arrayof_jint_disjoint_arraycopy; - StubRoutines::_jint_arraycopy = StubRoutines::_arrayof_jint_arraycopy; -#endif - //*** jlong // It is always aligned @@ -3178,7 +3071,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(true, entry, NULL, "arrayof_oop_arraycopy_uninit", /*dest_uninitialized*/true); -#ifdef _LP64 if (UseCompressedOops) { // With compressed oops we need unaligned versions, notice that we overwrite entry_oop_arraycopy. StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, &entry, @@ -3192,9 +3084,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(false, entry, NULL, "oop_arraycopy_uninit", /*dest_uninitialized*/true); - } else -#endif - { + } else { // oop arraycopy is always aligned on 32bit and 64bit without compressed oops StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy; StubRoutines::_oop_arraycopy = StubRoutines::_arrayof_oop_arraycopy; @@ -5104,17 +4994,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::Sparc::_stop_subroutine_entry = generate_stop_subroutine(); StubRoutines::Sparc::_flush_callers_register_windows_entry = generate_flush_callers_register_windows(); -#if !defined(COMPILER2) && !defined(_LP64) - StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); - StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg(); - StubRoutines::_atomic_add_entry = generate_atomic_add(); - StubRoutines::_atomic_xchg_ptr_entry = StubRoutines::_atomic_xchg_entry; - StubRoutines::_atomic_cmpxchg_ptr_entry = StubRoutines::_atomic_cmpxchg_entry; - StubRoutines::_atomic_cmpxchg_byte_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); - StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry; -#endif // COMPILER2 !=> _LP64 - // Build this early so it's available for the interpreter. StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", @@ -5222,11 +5101,9 @@ class StubGenerator: public StubCodeGenerator { void stub_prolog(StubCodeDesc* cdesc) { # ifdef ASSERT // put extra information in the stub code, to make it more readable -#ifdef _LP64 -// Write the high part of the address -// [RGV] Check if there is a dependency on the size of this prolog + // Write the high part of the address + // [RGV] Check if there is a dependency on the size of this prolog __ emit_data((intptr_t)cdesc >> 32, relocInfo::none); -#endif __ emit_data((intptr_t)cdesc, relocInfo::none); __ emit_data(++_stub_count, relocInfo::none); # endif diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp index fd4e3ffd149..aa6f30579cb 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -47,23 +47,14 @@ #include "utilities/debug.hpp" #include "utilities/macros.hpp" -#ifndef FAST_DISPATCH -#define FAST_DISPATCH 1 -#endif -#undef FAST_DISPATCH - // Size of interpreter code. Increase if too small. Interpreter will // fail with a guarantee ("not enough space for interpreter generation"); // if too small. // Run with +PrintInterpreter to get the VM to print out the size. // Max size with JVMTI -#ifdef _LP64 - // The sethi() instruction generates lots more instructions when shell - // stack limit is unlimited, so that's why this is much bigger. +// The sethi() instruction generates lots more instructions when shell +// stack limit is unlimited, so that's why this is much bigger. int TemplateInterpreter::InterpreterCodeSize = 260 * K; -#else -int TemplateInterpreter::InterpreterCodeSize = 230 * K; -#endif // Generation of Interpreter // @@ -75,41 +66,6 @@ int TemplateInterpreter::InterpreterCodeSize = 230 * K; //---------------------------------------------------------------------------------------------------- -#ifndef _LP64 -address TemplateInterpreterGenerator::generate_slow_signature_handler() { - address entry = __ pc(); - Argument argv(0, true); - - // We are in the jni transition frame. Save the last_java_frame corresponding to the - // outer interpreter frame - // - __ set_last_Java_frame(FP, noreg); - // make sure the interpreter frame we've pushed has a valid return pc - __ mov(O7, I7); - __ mov(Lmethod, G3_scratch); - __ mov(Llocals, G4_scratch); - __ save_frame(0); - __ mov(G2_thread, L7_thread_cache); - __ add(argv.address_in_frame(), O3); - __ mov(G2_thread, O0); - __ mov(G3_scratch, O1); - __ call(CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), relocInfo::runtime_call_type); - __ delayed()->mov(G4_scratch, O2); - __ mov(L7_thread_cache, G2_thread); - __ reset_last_Java_frame(); - - // load the register arguments (the C code packed them as varargs) - for (Argument ldarg = argv.successor(); ldarg.is_register(); ldarg = ldarg.successor()) { - __ ld_ptr(ldarg.address_in_frame(), ldarg.as_register()); - } - __ ret(); - __ delayed()-> - restore(O0, 0, Lscratch); // caller's Lscratch gets the result handler - return entry; -} - - -#else // LP64 passes floating point arguments in F1, F3, F5, etc. instead of // O0, O1, O2 etc.. // Doubles are passed in D0, D2, D4 @@ -206,7 +162,6 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { restore(O0, 0, Lscratch); // caller's Lscratch gets the result handler return entry; } -#endif void TemplateInterpreterGenerator::generate_counter_overflow(Label& Lcontinue) { @@ -253,11 +208,7 @@ void TemplateInterpreterGenerator::save_native_result(void) { // save and restore any potential method result value around the unlocking operation __ stf(FloatRegisterImpl::D, F0, d_tmp); -#ifdef _LP64 __ stx(O0, l_tmp); -#else - __ std(O0, l_tmp); -#endif } void TemplateInterpreterGenerator::restore_native_result(void) { @@ -266,11 +217,7 @@ void TemplateInterpreterGenerator::restore_native_result(void) { // Restore any method result value __ ldf(FloatRegisterImpl::D, d_tmp, F0); -#ifdef _LP64 __ ldx(l_tmp, O0); -#else - __ ldd(l_tmp, O0); -#endif } address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) { @@ -340,22 +287,6 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ profile_return_type(O0, G3_scratch, G1_scratch); } -#if !defined(_LP64) && defined(COMPILER2) - // All return values are where we want them, except for Longs. C2 returns - // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. - // Since the interpreter will return longs in G1 and O0/O1 in the 32bit - // build even if we are returning from interpreted we just do a little - // stupid shuffing. - // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to - // do this here. Unfortunately if we did a rethrow we'd see an machepilog node - // first which would move g1 -> O0/O1 and destroy the exception we were throwing. - - if (state == ltos) { - __ srl (G1, 0, O1); - __ srlx(G1, 32, O0); - } -#endif // !_LP64 && COMPILER2 - // The callee returns with the stack possibly adjusted by adapter transition // We remove that possible adjustment here. // All interpreter local registers are untouched. Any result is passed back @@ -374,6 +305,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, parameter_size); // argument size in words __ sll(parameter_size, Interpreter::logStackElementSize, parameter_size); // each argument size in bytes __ add(Lesp, parameter_size, Lesp); // pop arguments + + __ check_and_handle_popframe(Gtemp); + __ check_and_handle_earlyret(Gtemp); + __ dispatch_next(state, step); return entry; @@ -438,9 +373,6 @@ address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type case T_BYTE : __ sll(O0, 24, O0); __ sra(O0, 24, Itos_i); break; case T_SHORT : __ sll(O0, 16, O0); __ sra(O0, 16, Itos_i); break; case T_LONG : -#ifndef _LP64 - __ mov(O1, Itos_l2); // move other half of long -#endif // ifdef or no ifdef, fall through to the T_INT case case T_INT : __ mov(O0, Itos_i); break; case T_VOID : /* nothing to do */ break; case T_FLOAT : assert(F0 == Ftos_f, "fix this code" ); break; @@ -466,12 +398,6 @@ address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - __ dispatch_next(state); - return entry; -} - // // Helpers for commoning out cases in the various type of method entries. // @@ -886,20 +812,13 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { __ st_ptr(mirror, FP, (frame::interpreter_frame_mirror_offset * wordSize) + STACK_BIAS); __ get_constant_pool_cache( LcpoolCache ); // set LcpoolCache __ sub(FP, rounded_vm_local_words * BytesPerWord, Lmonitors ); // set Lmonitors -#ifdef _LP64 __ add( Lmonitors, STACK_BIAS, Lmonitors ); // Account for 64 bit stack bias -#endif __ sub(Lmonitors, BytesPerWord, Lesp); // set Lesp // setup interpreter activation registers __ sub(Gargs, BytesPerWord, Llocals); // set Llocals if (ProfileInterpreter) { -#ifdef FAST_DISPATCH - // FAST_DISPATCH and ProfileInterpreter are mutually exclusive since - // they both use I2. - assert(0, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive"); -#endif // FAST_DISPATCH __ set_method_data_pointer(); } @@ -1483,12 +1402,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Move the result handler address __ mov(Lscratch, G3_scratch); // return possible result to the outer frame -#ifndef __LP64 - __ mov(O0, I0); - __ restore(O1, G0, O1); -#else __ restore(O0, G0, O0); -#endif /* __LP64 */ // Move result handler to expected register __ mov(G3_scratch, Lscratch); @@ -1568,17 +1482,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { restore_native_result(); } -#if defined(COMPILER2) && !defined(_LP64) - - // C2 expects long results in G1 we can't tell if we're returning to interpreted - // or compiled so just be safe. - - __ sllx(O0, 32, G1); // Shift bits into high G1 - __ srl (O1, 0, O1); // Zero extend O1 - __ or3 (O1, G1, G1); // OR 64 bits into G1 - -#endif /* COMPILER2 && !_LP64 */ - // dispose of return address and remove activation #ifdef ASSERT { @@ -1651,11 +1554,6 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { generate_fixed_frame(false); -#ifdef FAST_DISPATCH - __ set((intptr_t)Interpreter::dispatch_table(), IdispatchTables); - // set bytecode dispatch table base -#endif - // // Code to initialize the extra (i.e. non-parm) locals // diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index f828aa0e370..af53a865318 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -248,12 +248,7 @@ void TemplateTable::iconst(int value) { void TemplateTable::lconst(int value) { transition(vtos, ltos); assert(value >= 0, "check this code"); -#ifdef _LP64 __ set(value, Otos_l); -#else - __ set(value, Otos_l2); - __ clr( Otos_l1); -#endif } @@ -406,24 +401,12 @@ void TemplateTable::ldc2_w() { // Check out Conversions.java for an example. // Also ConstantPool::header_size() is 20, which makes it very difficult // to double-align double on the constant pool. SG, 11/7/97 -#ifdef _LP64 __ ldf(FloatRegisterImpl::D, G3_scratch, base_offset, Ftos_d); -#else - FloatRegister f = Ftos_d; - __ ldf(FloatRegisterImpl::S, G3_scratch, base_offset, f); - __ ldf(FloatRegisterImpl::S, G3_scratch, base_offset + sizeof(jdouble)/2, - f->successor()); -#endif __ push(dtos); __ ba_short(exit); __ bind(Long); -#ifdef _LP64 __ ldx(G3_scratch, base_offset, Otos_l); -#else - __ ld(G3_scratch, base_offset, Otos_l); - __ ld(G3_scratch, base_offset + sizeof(jlong)/2, Otos_l->successor()); -#endif __ push(ltos); __ bind(exit); @@ -1128,19 +1111,11 @@ void TemplateTable::lop2(Operation op) { transition(ltos, ltos); __ pop_l(O2); switch (op) { -#ifdef _LP64 case add: __ add(O2, Otos_l, Otos_l); break; case sub: __ sub(O2, Otos_l, Otos_l); break; case _and: __ and3(O2, Otos_l, Otos_l); break; case _or: __ or3(O2, Otos_l, Otos_l); break; case _xor: __ xor3(O2, Otos_l, Otos_l); break; -#else - case add: __ addcc(O3, Otos_l2, Otos_l2); __ addc(O2, Otos_l1, Otos_l1); break; - case sub: __ subcc(O3, Otos_l2, Otos_l2); __ subc(O2, Otos_l1, Otos_l1); break; - case _and: __ and3(O3, Otos_l2, Otos_l2); __ and3(O2, Otos_l1, Otos_l1); break; - case _or: __ or3(O3, Otos_l2, Otos_l2); __ or3(O2, Otos_l1, Otos_l1); break; - case _xor: __ xor3(O3, Otos_l2, Otos_l2); __ xor3(O2, Otos_l1, Otos_l1); break; -#endif default: ShouldNotReachHere(); } } @@ -1171,14 +1146,10 @@ void TemplateTable::idiv() { Label regular; __ cmp(Otos_i, -1); __ br(Assembler::notEqual, false, Assembler::pt, regular); -#ifdef _LP64 // Don't put set in delay slot // Set will turn into multiple instructions in 64 bit mode __ delayed()->nop(); __ set(min_int, G4_scratch); -#else - __ delayed()->set(min_int, G4_scratch); -#endif Label done; __ cmp(O1, G4_scratch); __ br(Assembler::equal, true, Assembler::pt, done); @@ -1202,11 +1173,7 @@ void TemplateTable::irem() { void TemplateTable::lmul() { transition(ltos, ltos); __ pop_l(O2); -#ifdef _LP64 __ mulx(Otos_l, O2, Otos_l); -#else - __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::lmul)); -#endif } @@ -1216,15 +1183,9 @@ void TemplateTable::ldiv() { // check for zero __ pop_l(O2); -#ifdef _LP64 __ tst(Otos_l); __ throw_if_not_xcc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); __ sdivx(O2, Otos_l, Otos_l); -#else - __ orcc(Otos_l1, Otos_l2, G0); - __ throw_if_not_icc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); - __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); -#endif } @@ -1233,17 +1194,11 @@ void TemplateTable::lrem() { // check for zero __ pop_l(O2); -#ifdef _LP64 __ tst(Otos_l); __ throw_if_not_xcc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); __ sdivx(O2, Otos_l, Otos_l2); __ mulx (Otos_l2, Otos_l, Otos_l2); __ sub (O2, Otos_l2, Otos_l); -#else - __ orcc(Otos_l1, Otos_l2, G0); - __ throw_if_not_icc(Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); - __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); -#endif } @@ -1251,11 +1206,7 @@ void TemplateTable::lshl() { transition(itos, ltos); // %%%% could optimize, fill delay slot or opt for ultra __ pop_l(O2); // shift value in O2, O3 -#ifdef _LP64 __ sllx(O2, Otos_i, Otos_l); -#else - __ lshl(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); -#endif } @@ -1263,11 +1214,7 @@ void TemplateTable::lshr() { transition(itos, ltos); // %%%% see lshl comment __ pop_l(O2); // shift value in O2, O3 -#ifdef _LP64 __ srax(O2, Otos_i, Otos_l); -#else - __ lshr(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); -#endif } @@ -1276,11 +1223,7 @@ void TemplateTable::lushr() { transition(itos, ltos); // %%%% see lshl comment __ pop_l(O2); // shift value in O2, O3 -#ifdef _LP64 __ srlx(O2, Otos_i, Otos_l); -#else - __ lushr(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); -#endif } @@ -1293,15 +1236,9 @@ void TemplateTable::fop2(Operation op) { case div: __ pop_f(F4); __ fdiv(FloatRegisterImpl::S, F4, Ftos_f, Ftos_f); break; case rem: assert(Ftos_f == F0, "just checking"); -#ifdef _LP64 // LP64 calling conventions use F1, F3 for passing 2 floats __ pop_f(F1); __ fmov(FloatRegisterImpl::S, Ftos_f, F3); -#else - __ pop_i(O0); - __ stf(FloatRegisterImpl::S, Ftos_f, __ d_tmp); - __ ld( __ d_tmp, O1 ); -#endif __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::frem)); assert( Ftos_f == F0, "fix this code" ); break; @@ -1319,18 +1256,9 @@ void TemplateTable::dop2(Operation op) { case mul: __ pop_d(F4); __ fmul(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; case div: __ pop_d(F4); __ fdiv(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; case rem: -#ifdef _LP64 // Pass arguments in D0, D2 __ fmov(FloatRegisterImpl::D, Ftos_f, F2 ); __ pop_d( F0 ); -#else - // Pass arguments in O0O1, O2O3 - __ stf(FloatRegisterImpl::D, Ftos_f, __ d_tmp); - __ ldd( __ d_tmp, O2 ); - __ pop_d(Ftos_f); - __ stf(FloatRegisterImpl::D, Ftos_f, __ d_tmp); - __ ldd( __ d_tmp, O0 ); -#endif __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::drem)); assert( Ftos_d == F0, "fix this code" ); break; @@ -1348,11 +1276,7 @@ void TemplateTable::ineg() { void TemplateTable::lneg() { transition(ltos, ltos); -#ifdef _LP64 __ sub(G0, Otos_l, Otos_l); -#else - __ lneg(Otos_l1, Otos_l2); -#endif } @@ -1437,15 +1361,8 @@ void TemplateTable::convert() { Label done; switch (bytecode()) { case Bytecodes::_i2l: -#ifdef _LP64 // Sign extend the 32 bits __ sra ( Otos_i, 0, Otos_l ); -#else - __ addcc(Otos_i, 0, Otos_l2); - __ br(Assembler::greaterEqual, true, Assembler::pt, done); - __ delayed()->clr(Otos_l1); - __ set(~0, Otos_l1); -#endif break; case Bytecodes::_i2f: @@ -1476,12 +1393,8 @@ void TemplateTable::convert() { break; case Bytecodes::_l2i: -#ifndef _LP64 - __ mov(Otos_l2, Otos_i); -#else // Sign-extend into the high 32 bits __ sra(Otos_l, 0, Otos_i); -#endif break; case Bytecodes::_l2f: @@ -1512,11 +1425,7 @@ void TemplateTable::convert() { case Bytecodes::_f2l: // must uncache tos __ push_f(); -#ifdef _LP64 __ pop_f(F1); -#else - __ pop_i(O0); -#endif __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::f2l)); break; @@ -1528,13 +1437,8 @@ void TemplateTable::convert() { case Bytecodes::_d2l: // must uncache tos __ push_d(); -#ifdef _LP64 // LP64 calling conventions pass first double arg in D0 __ pop_d( Ftos_d ); -#else - __ pop_i( O0 ); - __ pop_i( O1 ); -#endif __ call_VM_leaf(Lscratch, bytecode() == Bytecodes::_d2i ? CAST_FROM_FN_PTR(address, SharedRuntime::d2i) @@ -1554,13 +1458,8 @@ void TemplateTable::convert() { void TemplateTable::lcmp() { transition(ltos, itos); -#ifdef _LP64 __ pop_l(O1); // pop off value 1, value 2 is in O0 __ lcmp( O1, Otos_l, Otos_i ); -#else - __ pop_l(O2); // cmp O2,3 to O0,1 - __ lcmp( O2, O3, Otos_l1, Otos_l2, Otos_i ); -#endif } @@ -1756,7 +1655,6 @@ void TemplateTable::ret() { __ access_local_returnAddress(G3_scratch, Otos_i); // Otos_i contains the bci, compute the bcp from that -#ifdef _LP64 #ifdef ASSERT // jsr result was labeled as an 'itos' not an 'atos' because we cannot GC // the result. The return address (really a BCI) was stored with an @@ -1771,7 +1669,6 @@ void TemplateTable::ret() { __ stop("BCI is in the wrong register half?"); __ bind (zzz) ; } -#endif #endif __ profile_ret(vtos, Otos_i, G4_scratch); @@ -1808,10 +1705,8 @@ void TemplateTable::tableswitch() { // load lo, hi __ ld(O1, 1 * BytesPerInt, O2); // Low Byte __ ld(O1, 2 * BytesPerInt, O3); // High Byte -#ifdef _LP64 // Sign extend the 32 bits __ sra ( Otos_i, 0, Otos_i ); -#endif /* _LP64 */ // check against lo & hi __ cmp( Otos_i, O2); @@ -3346,9 +3241,7 @@ void TemplateTable::_new() { __ br(Assembler::notEqual, false, Assembler::pn, slow_case); __ delayed()->sll(Roffset, LogBytesPerWord, Roffset); // get InstanceKlass - //__ sll(Roffset, LogBytesPerWord, Roffset); // executed in delay slot - __ add(Roffset, sizeof(ConstantPool), Roffset); - __ ld_ptr(Rscratch, Roffset, RinstanceKlass); + __ load_resolved_klass_at_offset(Rscratch, Roffset, RinstanceKlass); // make sure klass is fully initialized: __ ldub(RinstanceKlass, in_bytes(InstanceKlass::init_state_offset()), G3_scratch); @@ -3400,11 +3293,7 @@ void TemplateTable::_new() { // Check if tlab should be discarded (refill_waste_limit >= free) __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), RtlabWasteLimitValue); __ sub(RendValue, RoldTopValue, RfreeValue); -#ifdef _LP64 __ srlx(RfreeValue, LogHeapWordSize, RfreeValue); -#else - __ srl(RfreeValue, LogHeapWordSize, RfreeValue); -#endif __ cmp_and_brx_short(RtlabWasteLimitValue, RfreeValue, Assembler::greaterEqualUnsigned, Assembler::pt, slow_case); // tlab waste is small // increment waste limit to prevent getting stuck on this slow path @@ -3574,8 +3463,9 @@ void TemplateTable::checkcast() { // Extract target class from constant pool __ bind(quicked); - __ add(Roffset, sizeof(ConstantPool), Roffset); - __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); + __ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass); + + __ bind(resolved); __ load_klass(Otos_i, RobjKlass); // get value klass @@ -3631,9 +3521,9 @@ void TemplateTable::instanceof() { // Extract target class from constant pool __ bind(quicked); - __ add(Roffset, sizeof(ConstantPool), Roffset); __ get_constant_pool(Lscratch); - __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); + __ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass); + __ bind(resolved); __ load_klass(Otos_i, RobjKlass); // get value klass diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 770ca6bf197..a5290a405fc 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -37,23 +37,40 @@ void VM_Version::initialize() { assert(_features != 0, "System pre-initialization is not complete."); guarantee(VM_Version::has_v9(), "only SPARC v9 is supported"); - PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes(); - PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes(); - PrefetchFieldsAhead = prefetch_fields_ahead(); + if (FLAG_IS_DEFAULT(PrefetchCopyIntervalInBytes)) { + FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, prefetch_copy_interval_in_bytes()); + } + if (FLAG_IS_DEFAULT(PrefetchScanIntervalInBytes)) { + FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, prefetch_scan_interval_in_bytes()); + } + if (FLAG_IS_DEFAULT(PrefetchFieldsAhead)) { + FLAG_SET_DEFAULT(PrefetchFieldsAhead, prefetch_fields_ahead()); + } // Allocation prefetch settings intx cache_line_size = prefetch_data_size(); - if( cache_line_size > AllocatePrefetchStepSize ) - AllocatePrefetchStepSize = cache_line_size; + if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize) && + (cache_line_size > AllocatePrefetchStepSize)) { + FLAG_SET_DEFAULT(AllocatePrefetchStepSize, cache_line_size); + } - AllocatePrefetchDistance = allocate_prefetch_distance(); - AllocatePrefetchStyle = allocate_prefetch_style(); + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 512); + } - if (!has_blk_init() || cache_line_size <= 0) { - if (AllocatePrefetchInstr == 1) { - warning("BIS instructions required for AllocatePrefetchInstr 1 unavailable"); - FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); + if ((AllocatePrefetchDistance == 0) && (AllocatePrefetchStyle != 0)) { + assert(!FLAG_IS_DEFAULT(AllocatePrefetchDistance), "default value should not be 0"); + if (!FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { + warning("AllocatePrefetchDistance is set to 0 which disable prefetching. Ignoring AllocatePrefetchStyle flag."); } + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 0); + } + + if ((AllocatePrefetchInstr == 1) && (!has_blk_init() || cache_line_size <= 0)) { + if (!FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { + warning("BIS instructions required for AllocatePrefetchInstr 1 unavailable"); + } + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); } UseSSE = 0; // Only on x86 and x64 @@ -70,12 +87,10 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { FLAG_SET_DEFAULT(OptoLoopAlignment, 4); } -#ifdef _LP64 // 32-bit oops don't make sense for the 64-bit VM on sparc // since the 32-bit VM has the same registers and smaller objects. Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes); -#endif // _LP64 #ifdef COMPILER2 // Indirect branch is the same cost as direct if (FLAG_IS_DEFAULT(UseJumpTables)) { @@ -123,9 +138,10 @@ void VM_Version::initialize() { } } - if (AllocatePrefetchInstr == 1) { - // Use allocation prefetch style 3 because BIS instructions - // require aligned memory addresses. + if ((AllocatePrefetchInstr == 1) && (AllocatePrefetchStyle != 3)) { + if (!FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { + warning("AllocatePrefetchStyle set to 3 because BIS instructions require aligned memory addresses"); + } FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3); } #endif /* COMPILER2 */ diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index f5cb00d75a7..8a6e72847b7 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -180,30 +180,13 @@ public: // Prefetch static intx prefetch_copy_interval_in_bytes() { - intx interval = PrefetchCopyIntervalInBytes; - return interval >= 0 ? interval : (has_v9() ? 512 : 0); + return (has_v9() ? 512 : 0); } static intx prefetch_scan_interval_in_bytes() { - intx interval = PrefetchScanIntervalInBytes; - return interval >= 0 ? interval : (has_v9() ? 512 : 0); + return (has_v9() ? 512 : 0); } static intx prefetch_fields_ahead() { - intx count = PrefetchFieldsAhead; - return count >= 0 ? count : (is_ultra3() ? 1 : 0); - } - - static intx allocate_prefetch_distance() { - // This method should be called before allocate_prefetch_style(). - intx count = AllocatePrefetchDistance; - if (count < 0) { // default is not defined ? - count = 512; - } - return count; - } - static intx allocate_prefetch_style() { - assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); - // Return 0 if AllocatePrefetchDistance was not defined. - return AllocatePrefetchDistance > 0 ? AllocatePrefetchStyle : 0; + return (is_ultra3() ? 1 : 0); } // Assembler testing diff --git a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp index 9e825aaa79e..3249b3a26f3 100644 --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -232,7 +232,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { MacroAssembler::instr_size_for_decode_klass_not_null() : 0); return basic + slop; } else { - const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + + const int basic = 34 * BytesPerInstWord + // shift;add for load_klass (only shift with zero heap based) (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); @@ -257,7 +257,6 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { // ld [ %g3 + 0xe8 ], %l2 // sll %l2, 2, %l2 // add %l2, 0x134, %l2 - // and %l2, -8, %l2 ! NOT_LP64 only // add %g3, %l2, %l2 // add %g3, 4, %g3 // ld [ %l2 ], %l5 diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 3c6d7b5cdd6..3bdc0ed3c30 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -2103,12 +2103,20 @@ void Assembler::jmpb(Label& L) { } void Assembler::ldmxcsr( Address src) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - prefix(src); - emit_int8(0x0F); - emit_int8((unsigned char)0xAE); - emit_operand(as_Register(2), src); + if (UseAVX > 0 ) { + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + vex_prefix(src, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(2), src); + } else { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + prefix(src); + emit_int8(0x0F); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(2), src); + } } void Assembler::leal(Register dst, Address src) { @@ -3313,6 +3321,11 @@ void Assembler::pause() { emit_int8((unsigned char)0x90); } +void Assembler::ud2() { + emit_int8(0x0F); + emit_int8(0x0B); +} + void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); InstructionMark im(this); @@ -4416,12 +4429,21 @@ void Assembler::sqrtss(XMMRegister dst, Address src) { } void Assembler::stmxcsr( Address dst) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - prefix(dst); - emit_int8(0x0F); - emit_int8((unsigned char)0xAE); - emit_operand(as_Register(3), dst); + if (UseAVX > 0 ) { + assert(VM_Version::supports_avx(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + vex_prefix(dst, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(3), dst); + } else { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + prefix(dst); + emit_int8(0x0F); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(3), dst); + } } void Assembler::subl(Address dst, int32_t imm32) { @@ -5070,6 +5092,42 @@ void Assembler::vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector emit_operand(dst, src); } +void Assembler::vfmadd231pd(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vfmadd231ps(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vfmadd231pd(XMMRegister dst, XMMRegister src1, Address src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + vex_prefix(src2, src1->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_operand(dst, src2); +} + +void Assembler::vfmadd231ps(XMMRegister dst, XMMRegister src1, Address src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_32bit); + vex_prefix(src2, src1->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_operand(dst, src2); +} + void Assembler::divpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); @@ -6620,10 +6678,11 @@ void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, in } void Assembler::vzeroupper() { - assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); - (void)vex_prefix_and_encode(0, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); - emit_int8(0x77); + if (VM_Version::supports_vzeroupper()) { + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + (void)vex_prefix_and_encode(0, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8(0x77); + } } #ifndef _LP64 diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index ada59ae288c..c4e6645e319 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1554,6 +1554,9 @@ private: void pause(); + // Undefined Instruction + void ud2(); + // SSE4.2 string instructions void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); void pcmpestri(XMMRegister xmm1, Address src, int imm8); @@ -1903,6 +1906,11 @@ private: void vmulpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); void vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void vfmadd231pd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void vfmadd231ps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void vfmadd231pd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void vfmadd231ps(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + // Divide Packed Floating-Point Values void divpd(XMMRegister dst, XMMRegister src); void divps(XMMRegister dst, XMMRegister src); diff --git a/hotspot/src/cpu/x86/vm/bytes_x86.hpp b/hotspot/src/cpu/x86/vm/bytes_x86.hpp index eb5ab17ca08..0169f04d611 100644 --- a/hotspot/src/cpu/x86/vm/bytes_x86.hpp +++ b/hotspot/src/cpu/x86/vm/bytes_x86.hpp @@ -36,36 +36,85 @@ class Bytes: AllStatic { #endif // AMD64 public: - // Returns true if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. For example, this is true for Intel x86, but false for Solaris - // on Sparc. - static inline bool is_Java_byte_ordering_different(){ return true; } - - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering - // (no special code is needed since x86 CPUs can access unaligned data) - static inline u2 get_native_u2(address p) { return *(u2*)p; } - static inline u4 get_native_u4(address p) { return *(u4*)p; } - static inline u8 get_native_u8(address p) { return *(u8*)p; } + template + static inline T get_native(const void* p) { + assert(p != NULL, "null pointer"); - static inline void put_native_u2(address p, u2 x) { *(u2*)p = x; } - static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; } - static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; } + T x; + if (is_ptr_aligned(p, sizeof(T))) { + x = *(T*)p; + } else { + memcpy(&x, p, sizeof(T)); + } + + return x; + } + + template + static inline void put_native(void* p, T x) { + assert(p != NULL, "null pointer"); + + if (is_ptr_aligned(p, sizeof(T))) { + *(T*)p = x; + } else { + memcpy(p, &x, sizeof(T)); + } + } + + static inline u2 get_native_u2(address p) { return get_native((void*)p); } + static inline u4 get_native_u4(address p) { return get_native((void*)p); } + static inline u8 get_native_u8(address p) { return get_native((void*)p); } + static inline void put_native_u2(address p, u2 x) { put_native((void*)p, x); } + static inline void put_native_u4(address p, u4 x) { put_native((void*)p, x); } + static inline void put_native_u8(address p, u8 x) { put_native((void*)p, x); } // Efficient reading and writing of unaligned unsigned data in Java // byte ordering (i.e. big-endian ordering). Byte-order reversal is // needed since x86 CPUs use little-endian format. - static inline u2 get_Java_u2(address p) { return swap_u2(get_native_u2(p)); } - static inline u4 get_Java_u4(address p) { return swap_u4(get_native_u4(p)); } - static inline u8 get_Java_u8(address p) { return swap_u8(get_native_u8(p)); } + template + static inline T get_Java(const address p) { + T x = get_native(p); - static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, swap_u2(x)); } - static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, swap_u4(x)); } - static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, swap_u8(x)); } + if (Endian::is_Java_byte_ordering_different()) { + x = swap(x); + } + return x; + } + + template + static inline void put_Java(address p, T x) { + if (Endian::is_Java_byte_ordering_different()) { + x = swap(x); + } + + put_native(p, x); + } + + static inline u2 get_Java_u2(address p) { return get_Java(p); } + static inline u4 get_Java_u4(address p) { return get_Java(p); } + static inline u8 get_Java_u8(address p) { return get_Java(p); } + + static inline void put_Java_u2(address p, u2 x) { put_Java(p, x); } + static inline void put_Java_u4(address p, u4 x) { put_Java(p, x); } + static inline void put_Java_u8(address p, u8 x) { put_Java(p, x); } // Efficient swapping of byte ordering + template + static T swap(T x) { + switch (sizeof(T)) { + case sizeof(u1): return x; + case sizeof(u2): return swap_u2(x); + case sizeof(u4): return swap_u4(x); + case sizeof(u8): return swap_u8(x); + default: + guarantee(false, "invalid size: " SIZE_FORMAT "\n", sizeof(T)); + return 0; + } + } + static inline u2 swap_u2(u2 x); // compiler-dependent implementation static inline u4 swap_u4(u4 x); // compiler-dependent implementation static inline u8 swap_u8(u8 x); diff --git a/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp b/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp index 6d91d1948e9..3ec182a350b 100644 --- a/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "c1/c1_FpuStackSim.hpp" #include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" +#include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" //-------------------------------------------------------- diff --git a/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp b/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp index 6b711506fab..d884ef2a87c 100644 --- a/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,6 +21,8 @@ * questions. */ +#include "precompiled.hpp" + #include "aot/compiledIC_aot.hpp" #include "code/codeCache.hpp" #include "memory/resourceArea.hpp" diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index 5673abb4448..b1206fa5b9a 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -160,25 +160,30 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseRTMDeopt, false, \ "Perform deopt and recompilation based on RTM abort ratio") \ \ - product(uintx, RTMRetryCount, 5, \ + product(int, RTMRetryCount, 5, \ "Number of RTM retries on lock abort or busy") \ - range(0, max_uintx) \ + range(0, max_jint) \ \ - experimental(intx, RTMSpinLoopCount, 100, \ + experimental(int, RTMSpinLoopCount, 100, \ "Spin count for lock to become free before RTM retry") \ + range(0, max_jint) \ \ - experimental(intx, RTMAbortThreshold, 1000, \ + experimental(int, RTMAbortThreshold, 1000, \ "Calculate abort ratio after this number of aborts") \ + range(0, max_jint) \ \ - experimental(intx, RTMLockingThreshold, 10000, \ + experimental(int, RTMLockingThreshold, 10000, \ "Lock count at which to do RTM lock eliding without " \ "abort ratio calculation") \ + range(0, max_jint) \ \ - experimental(intx, RTMAbortRatio, 50, \ + experimental(int, RTMAbortRatio, 50, \ "Lock abort ratio at which to stop use RTM lock eliding") \ + range(0, 100) /* natural range, checked in vm_version_x86.cpp */ \ \ - experimental(intx, RTMTotalCountIncrRate, 64, \ + experimental(int, RTMTotalCountIncrRate, 64, \ "Increment total RTM attempted lock count once every n times") \ + range(1, max_jint) \ \ experimental(intx, RTMLockingCalculationDelay, 0, \ "Number of milliseconds to wait before start calculating aborts " \ diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp index 331ac5d3405..d02dd6f18aa 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -509,7 +509,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( get_constant_pool(result); // load pointer for resolved_references[] objArray - movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes())); + movptr(result, Address(result, ConstantPool::cache_offset_in_bytes())); + movptr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes())); // JNIHandles::resolve(obj); movptr(result, Address(result, 0)); // Add in the index @@ -517,6 +518,14 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_index(Register cpool, + Register index, Register klass) { + movw(index, Address(cpool, index, Address::times_ptr, sizeof(ConstantPool))); + Register resolved_klasses = cpool; + movptr(resolved_klasses, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); + movptr(klass, Address(resolved_klasses, index, Address::times_ptr, Array::base_offset_in_bytes())); +} // Generate a subtype check: branch to ok_is_subtype if sub_klass is a // subtype of super_klass. @@ -1148,7 +1157,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) { movl(swap_reg, (int32_t)1); // Load (object->mark() | 1) into swap_reg %rax - orptr(swap_reg, Address(obj_reg, 0)); + orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // Save (object->mark() | 1) into BasicLock's displaced header movptr(Address(lock_reg, mark_offset), swap_reg); @@ -1157,7 +1166,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) { "displaced header must be first word in BasicObjectLock"); if (os::is_MP()) lock(); - cmpxchgptr(lock_reg, Address(obj_reg, 0)); + cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); if (PrintBiasedLockingStatistics) { cond_inc32(Assembler::zero, ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); @@ -1254,7 +1263,7 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) { // Atomic swap back the old header if (os::is_MP()) lock(); - cmpxchgptr(header_reg, Address(obj_reg, 0)); + cmpxchgptr(header_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // zero for simple unlock of a stack-lock case jcc(Assembler::zero, done); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp index 9ed5c2c9ad3..0095564c1b0 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler { int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table, bool verifyoop = true); @@ -61,6 +58,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void jump_to_entry(address entry); + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + void load_earlyret_value(TosState state); // Interpreter-specific registers @@ -123,6 +123,11 @@ class InterpreterMacroAssembler: public MacroAssembler { // load cpool->resolved_references(index); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return) + Register index, // the constant pool index (corrupted on return) + Register klass); // contains the Klass on return + NOT_LP64(void f2ieee();) // truncate ftos to 32bits NOT_LP64(void d2ieee();) // truncate dtos to 64bits diff --git a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp index e2ddb71aa9d..acb7034684e 100644 --- a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp +++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -65,7 +65,7 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); if (HotSpotObjectConstantImpl::compressed(constant)) { #ifdef _LP64 diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index 6b7f947de6b..90c7540914d 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -763,11 +763,13 @@ void MacroAssembler::reset_last_Java_frame(bool clear_fp) { // Always clear the pc because it could have been set by make_walkable() movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + vzeroupper(); } void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_java_fp, address last_java_pc) { + vzeroupper(); // determine last_java_sp register if (!last_java_sp->is_valid()) { last_java_sp = rsp; @@ -1482,7 +1484,7 @@ void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Registe movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort bind(L_rtm_retry); } - movptr(tmpReg, Address(objReg, 0)); + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased jcc(Assembler::notZero, IsInflated); @@ -1490,14 +1492,14 @@ void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Registe Label L_noincrement; if (RTMTotalCountIncrRate > 1) { // tmpReg, scrReg and flags are killed - branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_rdtsc(tmpReg, scrReg, RTMTotalCountIncrRate, L_noincrement); } assert(stack_rtm_counters != NULL, "should not be NULL when profiling RTM"); atomic_incptr(ExternalAddress((address)stack_rtm_counters->total_count_addr()), scrReg); bind(L_noincrement); } xbegin(L_on_abort); - movptr(tmpReg, Address(objReg, 0)); // fetch markword + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked jcc(Assembler::equal, DONE_LABEL); // all done if unlocked @@ -1551,14 +1553,14 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi Label L_noincrement; if (RTMTotalCountIncrRate > 1) { // tmpReg, scrReg and flags are killed - branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_rdtsc(tmpReg, scrReg, RTMTotalCountIncrRate, L_noincrement); } assert(rtm_counters != NULL, "should not be NULL when profiling RTM"); atomic_incptr(ExternalAddress((address)rtm_counters->total_count_addr()), scrReg); bind(L_noincrement); } xbegin(L_on_abort); - movptr(tmpReg, Address(objReg, 0)); + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); movptr(tmpReg, Address(tmpReg, owner_offset)); testptr(tmpReg, tmpReg); jcc(Assembler::zero, DONE_LABEL); @@ -1751,7 +1753,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg } #endif // INCLUDE_RTM_OPT - movptr(tmpReg, Address(objReg, 0)); // [FETCH] + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // [FETCH] testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased jccb(Assembler::notZero, IsInflated); @@ -1761,7 +1763,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg if (os::is_MP()) { lock(); } - cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg + cmpxchgptr(boxReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Updates tmpReg if (counters != NULL) { cond_inc32(Assembler::equal, ExternalAddress((address)counters->fast_path_entry_count_addr())); @@ -1982,7 +1984,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR if (UseRTMForStackLocks && use_rtm) { assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking"); Label L_regular_unlock; - movptr(tmpReg, Address(objReg, 0)); // fetch markword + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked jccb(Assembler::notEqual, L_regular_unlock); // if !HLE RegularLock @@ -1994,7 +1996,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock - movptr(tmpReg, Address(objReg, 0)); // Examine the object's markword + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Examine the object's markword testptr(tmpReg, markOopDesc::monitor_value); // Inflated? jccb (Assembler::zero, Stacked); @@ -2148,7 +2150,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR if (os::is_MP()) { lock(); } - cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box + cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box // Intention fall-thru into DONE_LABEL // DONE_LABEL is a hot target - we'd really like to place it at the @@ -2245,7 +2247,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR bind (Stacked); movptr(tmpReg, Address (boxReg, 0)); // re-fetch if (os::is_MP()) { lock(); } - cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box + cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box if (EmitSync & 65536) { bind (CheckSucc); @@ -3163,8 +3165,37 @@ void MacroAssembler::fmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegi } } +// dst = c = a * b + c +void MacroAssembler::vfmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len) { + Assembler::vfmadd231pd(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} +// dst = c = a * b + c +void MacroAssembler::vfmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len) { + Assembler::vfmadd231ps(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} +// dst = c = a * b + c +void MacroAssembler::vfmad(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len) { + Assembler::vfmadd231pd(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} + +// dst = c = a * b + c +void MacroAssembler::vfmaf(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len) { + Assembler::vfmadd231ps(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} void MacroAssembler::incrementl(AddressLiteral dst) { if (reachable(dst)) { @@ -3672,6 +3703,7 @@ void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp) // Always clear the pc because it could have been set by make_walkable() movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + vzeroupper(); } void MacroAssembler::restore_rax(Register tmp) { @@ -3714,6 +3746,7 @@ void MacroAssembler::set_last_Java_frame(Register java_thread, Register last_java_sp, Register last_java_fp, address last_java_pc) { + vzeroupper(); // determine java_thread register if (!java_thread->is_valid()) { java_thread = rdi; @@ -6552,10 +6585,8 @@ void MacroAssembler::restore_cpu_control_state_after_jni() { call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry())); } } - if (VM_Version::supports_avx()) { - // Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty. - vzeroupper(); - } + // Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty. + vzeroupper(); #ifndef _LP64 // Either restore the x87 floating pointer control word after returning diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 2c2b17c06ad..eae13b93d66 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -71,12 +71,6 @@ class MacroAssembler: public Assembler { bool check_exceptions // whether to check for pending exceptions after return ); - // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); // helpers for FPU flag access @@ -87,6 +81,12 @@ class MacroAssembler: public Assembler { public: MacroAssembler(CodeBuffer* code) : Assembler(code) {} + // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles PopFrame and ForceEarlyReturn requests. + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Support for NULL-checks // // Generates code that causes a NULL OS exception if the content of reg is NULL. @@ -456,6 +456,11 @@ class MacroAssembler: public Assembler { void fmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c); void fmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c); + void vfmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len); + void vfmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len); + void vfmad(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len); + void vfmaf(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len); + // same as fcmp2int, but using SSE2 void cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less); diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp deleted file mode 100644 index c2956a52a54..00000000000 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2004, 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. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // Load rax, with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - // -- must fit in 13-bit instruction immediate field. - __ movl(rax, (i << 8) + j); - __ jmp(common_code); - } - } - - __ bind(common_code); - -#ifdef WIN32 - // Expecting to be called with "thiscall" conventions -- the arguments - // are on the stack, except that the "this" pointer is in rcx. -#else - // Expecting to be called with Unix conventions -- the arguments - // are on the stack, including the "this" pointer. -#endif - - // In addition, rax was set (above) to the offset of the method in the - // table. - -#ifdef WIN32 - __ push(rcx); // save "this" -#endif - __ mov(rcx, rax); - __ shrptr(rcx, 8); // isolate vtable identifier. - __ shlptr(rcx, LogBytesPerWord); - Address index(noreg, rcx, Address::times_1); - ExternalAddress vtbl((address)vtbl_list); - __ movptr(rdx, ArrayAddress(vtbl, index)); // get correct vtable address. -#ifdef WIN32 - __ pop(rcx); // restore "this" -#else - __ movptr(rcx, Address(rsp, BytesPerWord)); // fetch "this" -#endif - __ movptr(Address(rcx, 0), rdx); // update vtable pointer. - - __ andptr(rax, 0x00ff); // isolate vtable method index - __ shlptr(rax, LogBytesPerWord); - __ addptr(rax, rdx); // address of real method pointer. - __ jmp(Address(rax, 0)); // get real method pointer. - - __ flush(); - - *mc_top = (char*)__ pc(); -} diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp deleted file mode 100644 index 4ff6cc955d7..00000000000 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2004, 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. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // Load eax with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - // -- must fit in 13-bit instruction immediate field. - __ movl(rax, (i << 8) + j); - __ jmp(common_code); - } - } - - __ bind(common_code); - - // Expecting to be called with "thiscall" convections -- the arguments - // are on the stack and the "this" pointer is in c_rarg0. In addition, rax - // was set (above) to the offset of the method in the table. - - __ push(c_rarg1); // save & free register - __ push(c_rarg0); // save "this" - __ mov(c_rarg0, rax); - __ shrptr(c_rarg0, 8); // isolate vtable identifier. - __ shlptr(c_rarg0, LogBytesPerWord); - __ lea(c_rarg1, ExternalAddress((address)vtbl_list)); // ptr to correct vtable list. - __ addptr(c_rarg1, c_rarg0); // ptr to list entry. - __ movptr(c_rarg1, Address(c_rarg1, 0)); // get correct vtable address. - __ pop(c_rarg0); // restore "this" - __ movptr(Address(c_rarg0, 0), c_rarg1); // update vtable pointer. - - __ andptr(rax, 0x00ff); // isolate vtable method index - __ shlptr(rax, LogBytesPerWord); - __ addptr(rax, c_rarg1); // address of real method pointer. - __ pop(c_rarg1); // restore register. - __ movptr(rax, Address(rax, 0)); // get real method pointer. - __ jmp(rax); // jump to the real method. - - __ flush(); - - *mc_top = (char*)__ pc(); -} diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 399172b5a15..c1934b6a2d6 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -65,7 +65,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Register temp = rdi; Register temp2 = noreg; LP64_ONLY(temp2 = rscratch1); // used by MacroAssembler::cmpptr @@ -169,8 +169,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(method_temp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(method_temp); + __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -331,7 +332,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method( rbx_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -383,14 +385,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ movptr(rbx_method, member_vmtarget); + __ load_heap_oop(rbx_method, member_vmtarget); + __ movptr(rbx_method, vmtarget_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ movptr(rbx_method, member_vmtarget); + __ load_heap_oop(rbx_method, member_vmtarget); + __ movptr(rbx_method, vmtarget_method); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index 47b9fe5c627..96430cc25d9 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -41,6 +41,7 @@ #ifdef COMPILER2 #include "opto/runtime.hpp" #endif +#include "vm_version_x86.hpp" #define __ masm-> @@ -120,8 +121,8 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ int zmm_bytes = num_xmm_regs * 32; #ifdef COMPILER2 if (save_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); // Save upper half of YMM registers int vect_bytes = ymm_bytes; if (UseAVX > 2) { @@ -219,6 +220,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ } } } + __ vzeroupper(); // Set an oopmap for the call site. This oopmap will map all // oop-registers and debug-info registers as callee-saved. This @@ -269,8 +271,8 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve int additional_frame_bytes = 0; #ifdef COMPILER2 if (restore_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); // Save upper half of YMM registers additional_frame_bytes = ymm_bytes; if (UseAVX > 2) { @@ -285,6 +287,8 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve int off = xmm0_off; int delta = xmm1_off - off; + __ vzeroupper(); + if (UseSSE == 1) { // Restore XMM registers assert(additional_frame_bytes == 0, ""); @@ -1994,7 +1998,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ movptr(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %rax, - __ orptr(swap_reg, Address(obj_reg, 0)); + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // Save (object->mark() | 1) into BasicLock's displaced header __ movptr(Address(lock_reg, mark_word_offset), swap_reg); @@ -2005,7 +2009,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // src -> dest iff dest == rax, else rax, <- dest // *obj_reg = lock_reg iff *obj_reg == rax, else rax, = *(obj_reg) - __ cmpxchgptr(lock_reg, Address(obj_reg, 0)); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::equal, lock_done); // Test if the oopMark is an obvious stack pointer, i.e., @@ -2123,6 +2127,8 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // preserved and correspond to the bcp/locals pointers. So we do a runtime call // by hand. // + __ vzeroupper(); + save_native_result(masm, ret_type, stack_slots); __ push(thread); if (!is_critical_native) { @@ -2198,7 +2204,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // src -> dest iff dest == rax, else rax, <- dest // *obj_reg = rbx, iff *obj_reg == rax, else rax, = *(obj_reg) - __ cmpxchgptr(rbx, Address(obj_reg, 0)); + __ cmpxchgptr(rbx, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::notEqual, slow_path_unlock); // slow path re-enters here @@ -2304,7 +2310,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // BEGIN Slow path unlock __ bind(slow_path_unlock); - + __ vzeroupper(); // Slow path unlock if (ret_type == T_FLOAT || ret_type == T_DOUBLE ) { @@ -2349,6 +2355,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // SLOW PATH Reguard the stack if needed __ bind(reguard); + __ vzeroupper(); save_native_result(masm, ret_type, stack_slots); { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index d81e965d05d..c0dc2ac902d 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -47,6 +47,7 @@ #if INCLUDE_JVMCI #include "jvmci/jvmciJavaClasses.hpp" #endif +#include "vm_version_x86.hpp" #define __ masm-> @@ -151,8 +152,8 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ } #if defined(COMPILER2) || INCLUDE_JVMCI if (save_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); } #else assert(!save_vectors, "vectors are generated only by C2 and JVMCI"); @@ -206,6 +207,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ } } } + __ vzeroupper(); if (frame::arg_reg_save_area_bytes != 0) { // Allocate argument register save area __ subptr(rsp, frame::arg_reg_save_area_bytes); @@ -322,13 +324,15 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve #if defined(COMPILER2) || INCLUDE_JVMCI if (restore_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); } #else assert(!restore_vectors, "vectors are generated only by C2"); #endif + __ vzeroupper(); + // On EVEX enabled targets everything is handled in pop fpu state if (restore_vectors) { // Restore upper half of YMM registers (0..15) @@ -528,7 +532,7 @@ static void patch_callers_callsite(MacroAssembler *masm) { // align stack so push_CPU_state doesn't fault __ andptr(rsp, -(StackAlignmentInBytes)); __ push_CPU_state(); - + __ vzeroupper(); // VM needs caller's callsite // VM needs target method // This needs to be a long call since we will relocate this adapter to @@ -547,6 +551,7 @@ static void patch_callers_callsite(MacroAssembler *masm) { __ addptr(rsp, frame::arg_reg_save_area_bytes); } + __ vzeroupper(); __ pop_CPU_state(); // restore sp __ mov(rsp, r13); @@ -1465,7 +1470,6 @@ static void check_needs_gc_for_critical_native(MacroAssembler* masm, save_or_restore_arguments(masm, stack_slots, total_in_args, arg_save_area, NULL, in_regs, in_sig_bt); - __ bind(cont); #ifdef ASSERT if (StressCriticalJNINatives) { @@ -2368,7 +2372,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ movl(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %rax - __ orptr(swap_reg, Address(obj_reg, 0)); + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // Save (object->mark() | 1) into BasicLock's displaced header __ movptr(Address(lock_reg, mark_word_offset), swap_reg); @@ -2378,7 +2382,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, } // src -> dest iff dest == rax else rax <- dest - __ cmpxchgptr(lock_reg, Address(obj_reg, 0)); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::equal, lock_done); // Hmm should this move to the slow path code area??? @@ -2485,6 +2489,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // preserved and correspond to the bcp/locals pointers. So we do a runtime call // by hand. // + __ vzeroupper(); save_native_result(masm, ret_type, stack_slots); __ mov(c_rarg0, r15_thread); __ mov(r12, rsp); // remember sp @@ -2555,7 +2560,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, if (os::is_MP()) { __ lock(); } - __ cmpxchgptr(old_hdr, Address(obj_reg, 0)); + __ cmpxchgptr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::notEqual, slow_path_unlock); // slow path re-enters here @@ -2658,7 +2663,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // If we haven't already saved the native result we must save it now as xmm registers // are still exposed. - + __ vzeroupper(); if (ret_type == T_FLOAT || ret_type == T_DOUBLE ) { save_native_result(masm, ret_type, stack_slots); } @@ -2704,6 +2709,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // SLOW PATH Reguard the stack if needed __ bind(reguard); + __ vzeroupper(); save_native_result(masm, ret_type, stack_slots); __ mov(r12, rsp); // remember sp __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index d32917a5ab0..25eb6384c6b 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -1012,6 +1012,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(rdi); __ pop(rsi); __ leave(); // required for proper stackwalking of RuntimeStub frame + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ ret(0); return start; @@ -1247,6 +1248,7 @@ class StubGenerator: public StubCodeGenerator { } inc_copy_counter_np(T_LONG); __ leave(); // required for proper stackwalking of RuntimeStub frame + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ ret(0); return start; @@ -3365,6 +3367,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(rbx); __ pop(rdi); __ pop(rsi); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -3422,6 +3425,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(h); __ pop(g); __ pop(d); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 48be33ae526..bbe81875e91 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -402,6 +402,7 @@ class StubGenerator: public StubCodeGenerator { __ addptr(rsp, -rsp_after_call_off * wordSize); // return + __ vzeroupper(); __ pop(rbp); __ ret(0); @@ -1554,6 +1555,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1643,6 +1645,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1652,6 +1655,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1746,6 +1750,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1771,6 +1776,7 @@ class StubGenerator: public StubCodeGenerator { __ generate_fill(t, aligned, to, value, count, rax, xmm0); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); return start; @@ -1847,6 +1853,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1856,6 +1863,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1945,6 +1953,7 @@ class StubGenerator: public StubCodeGenerator { } restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2030,6 +2039,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2043,6 +2053,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2120,6 +2131,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); } @@ -2137,6 +2149,7 @@ class StubGenerator: public StubCodeGenerator { } else { inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free } + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2203,6 +2216,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); } @@ -2220,6 +2234,7 @@ class StubGenerator: public StubCodeGenerator { } else { inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free } + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -3774,7 +3789,7 @@ class StubGenerator: public StubCodeGenerator { buf, state, ofs, limit, rsp, multi_block, shuf_mask); } __ addptr(rsp, 4 * wordSize); - + __ vzeroupper(); __ leave(); __ ret(0); return start; @@ -3808,6 +3823,7 @@ class StubGenerator: public StubCodeGenerator { __ sha512_AVX2(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4, buf, state, ofs, limit, rsp, multi_block, shuf_mask); + __ vzeroupper(); __ leave(); __ ret(0); return start; @@ -4281,7 +4297,6 @@ class StubGenerator: public StubCodeGenerator { __ BIND(L_exit); __ pshufb(xmm_temp6, xmm_temp10); // Byte swap 16-byte result __ movdqu(Address(state, 0), xmm_temp6); // store the result - __ leave(); __ ret(0); return start; @@ -4321,6 +4336,7 @@ class StubGenerator: public StubCodeGenerator { __ kernel_crc32(crc, buf, len, table, tmp); __ movl(rax, crc); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4380,6 +4396,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(z); __ pop(y); #endif + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4494,6 +4511,7 @@ class StubGenerator: public StubCodeGenerator { __ vectorized_mismatch(obja, objb, length, scale, result, tmp1, tmp2, vec0, vec1, vec2); + __ vzeroupper(); __ leave(); __ ret(0); @@ -4618,7 +4636,7 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("Entry:"); __ enter(); // required for proper stackwalking of RuntimeStub frame - __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp); + __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp index 9c02d44cdb8..e0a03daa358 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp @@ -171,16 +171,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common( return entry; } - -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - // NULL last_sp until next java call - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - __ dispatch_next(state); - return entry; -} - - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -230,6 +220,17 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); __ andl(flags, ConstantPoolCacheEntry::parameter_size_mask); __ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale())); + + const Register java_thread = NOT_LP64(rcx) LP64_ONLY(r15_thread); + if (JvmtiExport::can_pop_frame()) { + NOT_LP64(__ get_thread(java_thread)); + __ check_and_handle_popframe(java_thread); + } + if (JvmtiExport::can_force_early_return()) { + NOT_LP64(__ get_thread(java_thread)); + __ check_and_handle_earlyret(java_thread); + } + __ dispatch_next(state, step); return entry; diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp index 3d2f57f37bc..69623f9783c 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp @@ -3846,7 +3846,7 @@ void TemplateTable::_new() { __ jcc(Assembler::notEqual, slow_case_no_pop); // get InstanceKlass - __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool))); + __ load_resolved_klass_at_index(rcx, rdx, rcx); __ push(rcx); // save the contexts of klass for initializing the header // make sure klass is initialized & doesn't have finalizer @@ -4061,8 +4061,7 @@ void TemplateTable::checkcast() { // Get superklass in rax and subklass in rbx __ bind(quicked); __ mov(rdx, rax); // Save object in rdx; rax needed for subtype check - __ movptr(rax, Address(rcx, rbx, - Address::times_ptr, sizeof(ConstantPool))); + __ load_resolved_klass_at_index(rcx, rbx, rax); __ bind(resolved); __ load_klass(rbx, rdx); @@ -4128,8 +4127,7 @@ void TemplateTable::instanceof() { // Get superklass in rax and subklass in rdx __ bind(quicked); __ load_klass(rdx, rax); - __ movptr(rax, Address(rcx, rbx, - Address::times_ptr, sizeof(ConstantPool))); + __ load_resolved_klass_at_index(rcx, rbx, rax); __ bind(resolved); diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 0307107ad9b..7fc5e451d08 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -74,6 +74,7 @@ declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) \ - declare_preprocessor_constant("VM_Version::CPU_FMA", CPU_FMA) + declare_preprocessor_constant("VM_Version::CPU_FMA", CPU_FMA) \ + declare_preprocessor_constant("VM_Version::CPU_VZEROUPPER", CPU_VZEROUPPER) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 197079ba1c7..db1930c382e 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -436,14 +436,14 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movl(rax, 0x10000); __ andl(rax, Address(rsi, 4)); __ cmpl(rax, 0x10000); - __ jccb(Assembler::notEqual, legacy_save_restore); + __ jcc(Assembler::notEqual, legacy_save_restore); // check _cpuid_info.xem_xcr0_eax.bits.opmask // check _cpuid_info.xem_xcr0_eax.bits.zmm512 // check _cpuid_info.xem_xcr0_eax.bits.zmm32 __ movl(rax, 0xE0); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm __ cmpl(rax, 0xE0); - __ jccb(Assembler::notEqual, legacy_save_restore); + __ jcc(Assembler::notEqual, legacy_save_restore); // If UseAVX is unitialized or is set by the user to include EVEX if (use_evex) { @@ -469,11 +469,12 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ evmovdqul(xmm7, Address(rsp, 0), Assembler::AVX_512bit); __ addptr(rsp, 64); #endif // _WINDOWS + generate_vzeroupper(wrapup); VM_Version::clean_cpuFeatures(); UseAVX = saved_useavx; UseSSE = saved_usesse; __ jmp(wrapup); - } + } __ bind(legacy_save_restore); // AVX check @@ -498,6 +499,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ vmovdqu(xmm7, Address(rsp, 0)); __ addptr(rsp, 32); #endif // _WINDOWS + generate_vzeroupper(wrapup); VM_Version::clean_cpuFeatures(); UseAVX = saved_useavx; UseSSE = saved_usesse; @@ -513,6 +515,21 @@ class VM_Version_StubGenerator: public StubCodeGenerator { return start; }; + void generate_vzeroupper(Label& L_wrapup) { +# define __ _masm-> + __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); + __ cmpl(Address(rsi, 4), 0x756e6547); // 'uneG' + __ jcc(Assembler::notEqual, L_wrapup); + __ movl(rcx, 0x0FFF0FF0); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); + __ andl(rcx, Address(rsi, 0)); + __ cmpl(rcx, 0x00050670); // If it is Xeon Phi 3200/5200/7200 + __ jcc(Assembler::equal, L_wrapup); + __ cmpl(rcx, 0x00080650); // If it is Future Xeon Phi + __ jcc(Assembler::equal, L_wrapup); + __ vzeroupper(); +# undef __ + } }; void VM_Version::get_processor_features() { @@ -619,17 +636,24 @@ void VM_Version::get_processor_features() { if (UseAVX < 2) _features &= ~CPU_AVX2; - if (UseAVX < 1) + if (UseAVX < 1) { _features &= ~CPU_AVX; - - if (!UseAES && !FLAG_IS_DEFAULT(UseAES)) - _features &= ~CPU_AES; + _features &= ~CPU_VZEROUPPER; + } if (logical_processors_per_package() == 1) { // HT processor could be installed on a system which doesn't support HT. _features &= ~CPU_HT; } + if( is_intel() ) { // Intel cpus specific settings + if ((cpu_family() == 0x06) && + ((extended_cpu_model() == 0x57) || // Xeon Phi 3200/5200/7200 + (extended_cpu_model() == 0x85))) { // Future Xeon Phi + _features &= ~CPU_VZEROUPPER; + } + } + char buf[256]; jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), @@ -785,7 +809,7 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } - if (supports_fma() && UseSSE >= 2) { + if (supports_fma() && UseSSE >= 2) { // Check UseSSE since FMA code uses SSE instructions if (FLAG_IS_DEFAULT(UseFMA)) { UseFMA = true; } @@ -917,16 +941,36 @@ void VM_Version::get_processor_features() { warning("MaxVectorSize must be a power of 2"); FLAG_SET_DEFAULT(MaxVectorSize, 64); } - if (MaxVectorSize > 64) { - FLAG_SET_DEFAULT(MaxVectorSize, 64); - } - if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) { - // 32 bytes vectors (in YMM) are only supported with AVX+ - FLAG_SET_DEFAULT(MaxVectorSize, 16); - } if (UseSSE < 2) { // Vectors (in XMM) are only supported with SSE2+ - FLAG_SET_DEFAULT(MaxVectorSize, 0); + if (MaxVectorSize > 0) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be 0"); + FLAG_SET_DEFAULT(MaxVectorSize, 0); + } + } + else if (UseAVX == 0 || !os_supports_avx_vectors()) { + // 32 bytes vectors (in YMM) are only supported with AVX+ + if (MaxVectorSize > 16) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be <= 16"); + FLAG_SET_DEFAULT(MaxVectorSize, 16); + } + } + else if (UseAVX == 1 || UseAVX == 2) { + // 64 bytes vectors (in ZMM) are only supported with AVX 3 + if (MaxVectorSize > 32) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be <= 32"); + FLAG_SET_DEFAULT(MaxVectorSize, 32); + } + } + else if (UseAVX > 2 ) { + if (MaxVectorSize > 64) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be <= 64"); + FLAG_SET_DEFAULT(MaxVectorSize, 64); + } } #if defined(COMPILER2) && defined(ASSERT) if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) { @@ -1056,18 +1100,18 @@ void VM_Version::get_processor_features() { if ( cpu_family() == 0x15 ) { // On family 15h processors default is no sw prefetch if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { - AllocatePrefetchStyle = 0; + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 0); } // Also, if some other prefetch style is specified, default instruction type is PREFETCHW if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { - AllocatePrefetchInstr = 3; + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3); } // On family 15h processors use XMM and UnalignedLoadStores for Array Copy if (supports_sse2() && FLAG_IS_DEFAULT(UseXMMForArrayCopy)) { - UseXMMForArrayCopy = true; + FLAG_SET_DEFAULT(UseXMMForArrayCopy, true); } if (supports_sse2() && FLAG_IS_DEFAULT(UseUnalignedLoadStores)) { - UseUnalignedLoadStores = true; + FLAG_SET_DEFAULT(UseUnalignedLoadStores, true); } } @@ -1148,7 +1192,7 @@ void VM_Version::get_processor_features() { } } if(FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) { - AllocatePrefetchInstr = 3; + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3); } } @@ -1244,45 +1288,68 @@ void VM_Version::get_processor_features() { } #endif // COMPILER2 - if( AllocatePrefetchInstr == 3 && !supports_3dnow_prefetch() ) AllocatePrefetchInstr=0; - if( !supports_sse() && supports_3dnow_prefetch() ) AllocatePrefetchInstr = 3; + if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { + if (AllocatePrefetchInstr == 3 && !supports_3dnow_prefetch()) { + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); + } else if (!supports_sse() && supports_3dnow_prefetch()) { + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3); + } + } // Allocation prefetch settings intx cache_line_size = prefetch_data_size(); - if( cache_line_size > AllocatePrefetchStepSize ) - AllocatePrefetchStepSize = cache_line_size; + if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize) && + (cache_line_size > AllocatePrefetchStepSize)) { + FLAG_SET_DEFAULT(AllocatePrefetchStepSize, cache_line_size); + } - AllocatePrefetchDistance = allocate_prefetch_distance(); - AllocatePrefetchStyle = allocate_prefetch_style(); + if ((AllocatePrefetchDistance == 0) && (AllocatePrefetchStyle != 0)) { + assert(!FLAG_IS_DEFAULT(AllocatePrefetchDistance), "default value should not be 0"); + if (!FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { + warning("AllocatePrefetchDistance is set to 0 which disable prefetching. Ignoring AllocatePrefetchStyle flag."); + } + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 0); + } + + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + bool use_watermark_prefetch = (AllocatePrefetchStyle == 2); + FLAG_SET_DEFAULT(AllocatePrefetchDistance, allocate_prefetch_distance(use_watermark_prefetch)); + } if (is_intel() && cpu_family() == 6 && supports_sse3()) { - if (AllocatePrefetchStyle == 2) { // watermark prefetching on Core -#ifdef _LP64 - AllocatePrefetchDistance = 384; -#else - AllocatePrefetchDistance = 320; -#endif - } - if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus - AllocatePrefetchDistance = 192; - if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) { - FLAG_SET_DEFAULT(AllocatePrefetchLines, 4); - } + if (FLAG_IS_DEFAULT(AllocatePrefetchLines) && + supports_sse4_2() && supports_ht()) { // Nehalem based cpus + FLAG_SET_DEFAULT(AllocatePrefetchLines, 4); } #ifdef COMPILER2 - if (supports_sse4_2()) { - if (FLAG_IS_DEFAULT(UseFPUForSpilling)) { - FLAG_SET_DEFAULT(UseFPUForSpilling, true); - } + if (FLAG_IS_DEFAULT(UseFPUForSpilling) && supports_sse4_2()) { + FLAG_SET_DEFAULT(UseFPUForSpilling, true); } #endif } #ifdef _LP64 // Prefetch settings - PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes(); - PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes(); - PrefetchFieldsAhead = prefetch_fields_ahead(); + + // Prefetch interval for gc copy/scan == 9 dcache lines. Derived from + // 50-warehouse specjbb runs on a 2-way 1.8ghz opteron using a 4gb heap. + // Tested intervals from 128 to 2048 in increments of 64 == one cache line. + // 256 bytes (4 dcache lines) was the nearest runner-up to 576. + + // gc copy/scan is disabled if prefetchw isn't supported, because + // Prefetch::write emits an inlined prefetchw on Linux. + // Do not use the 3dnow prefetchw instruction. It isn't supported on em64t. + // The used prefetcht0 instruction works for both amd64 and em64t. + + if (FLAG_IS_DEFAULT(PrefetchCopyIntervalInBytes)) { + FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 576); + } + if (FLAG_IS_DEFAULT(PrefetchScanIntervalInBytes)) { + FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 576); + } + if (FLAG_IS_DEFAULT(PrefetchFieldsAhead)) { + FLAG_SET_DEFAULT(PrefetchFieldsAhead, 1); + } #endif if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp index 5a51889e06b..dfcdb48621a 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp @@ -291,6 +291,7 @@ protected: #define CPU_AVX512VL ((uint64_t)UCONST64(0x200000000)) // EVEX instructions with smaller vector length #define CPU_SHA ((uint64_t)UCONST64(0x400000000)) // SHA instructions #define CPU_FMA ((uint64_t)UCONST64(0x800000000)) // FMA instructions +#define CPU_VZEROUPPER ((uint64_t)UCONST64(0x1000000000)) // Vzeroupper instruction enum Extended_Family { // AMD @@ -468,6 +469,7 @@ protected: _cpuid_info.xem_xcr0_eax.bits.sse != 0 && _cpuid_info.xem_xcr0_eax.bits.ymm != 0) { result |= CPU_AVX; + result |= CPU_VZEROUPPER; if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0) result |= CPU_AVX2; if (_cpuid_info.sef_cpuid7_ebx.bits.avx512f != 0 && @@ -605,8 +607,8 @@ public: static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; } static void clean_cpuFeatures() { _features = 0; } - static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX); } - static void set_evex_cpuFeatures() { _features = (CPU_AVX512F | CPU_SSE | CPU_SSE2 ); } + static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); } + static void set_evex_cpuFeatures() { _features = (CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } // Initialization @@ -730,7 +732,9 @@ public: static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } static bool supports_sha() { return (_features & CPU_SHA) != 0; } - static bool supports_fma() { return (_features & CPU_FMA) != 0; } + static bool supports_fma() { return (_features & CPU_FMA) != 0 && supports_avx(); } + static bool supports_vzeroupper() { return (_features & CPU_VZEROUPPER) != 0; } + // Intel features static bool is_intel_family_core() { return is_intel() && extended_cpu_family() == CPU_FAMILY_INTEL_CORE; } @@ -778,9 +782,7 @@ public: static bool supports_compare_and_exchange() { return true; } - static intx allocate_prefetch_distance() { - // This method should be called before allocate_prefetch_style(). - // + static intx allocate_prefetch_distance(bool use_watermark_prefetch) { // Hardware prefetching (distance/size in bytes): // Pentium 3 - 64 / 32 // Pentium 4 - 256 / 128 @@ -796,58 +798,34 @@ public: // Core - 256 / prefetchnta // It will be used only when AllocatePrefetchStyle > 0 - intx count = AllocatePrefetchDistance; - if (count < 0) { // default ? - if (is_amd()) { // AMD - if (supports_sse2()) - count = 256; // Opteron - else - count = 128; // Athlon - } else { // Intel - if (supports_sse2()) - if (cpu_family() == 6) { - count = 256; // Pentium M, Core, Core2 - } else { - count = 512; // Pentium 4 - } - else - count = 128; // Pentium 3 (and all other old CPUs) + if (is_amd()) { // AMD + if (supports_sse2()) { + return 256; // Opteron + } else { + return 128; // Athlon + } + } else { // Intel + if (supports_sse3() && cpu_family() == 6) { + if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus + return 192; + } else if (use_watermark_prefetch) { // watermark prefetching on Core +#ifdef _LP64 + return 384; +#else + return 320; +#endif + } + } + if (supports_sse2()) { + if (cpu_family() == 6) { + return 256; // Pentium M, Core, Core2 + } else { + return 512; // Pentium 4 + } + } else { + return 128; // Pentium 3 (and all other old CPUs) } } - return count; - } - static intx allocate_prefetch_style() { - assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); - // Return 0 if AllocatePrefetchDistance was not defined. - return AllocatePrefetchDistance > 0 ? AllocatePrefetchStyle : 0; - } - - // Prefetch interval for gc copy/scan == 9 dcache lines. Derived from - // 50-warehouse specjbb runs on a 2-way 1.8ghz opteron using a 4gb heap. - // Tested intervals from 128 to 2048 in increments of 64 == one cache line. - // 256 bytes (4 dcache lines) was the nearest runner-up to 576. - - // gc copy/scan is disabled if prefetchw isn't supported, because - // Prefetch::write emits an inlined prefetchw on Linux. - // Do not use the 3dnow prefetchw instruction. It isn't supported on em64t. - // The used prefetcht0 instruction works for both amd64 and em64t. - static intx prefetch_copy_interval_in_bytes() { - intx interval = PrefetchCopyIntervalInBytes; - return interval >= 0 ? interval : 576; - } - static intx prefetch_scan_interval_in_bytes() { - intx interval = PrefetchScanIntervalInBytes; - return interval >= 0 ? interval : 576; - } - static intx prefetch_fields_ahead() { - intx count = PrefetchFieldsAhead; - return count >= 0 ? count : 1; - } - static uint32_t get_xsave_header_lower_segment() { - return _cpuid_info.xem_xcr0_eax.value; - } - static uint32_t get_xsave_header_upper_segment() { - return _cpuid_info.xem_xcr0_edx; } // SSE2 and later processors implement a 'pause' instruction diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad index 3dd25561c0d..afaa2da23c7 100644 --- a/hotspot/src/cpu/x86/vm/x86.ad +++ b/hotspot/src/cpu/x86/vm/x86.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +// 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 @@ -1387,7 +1387,7 @@ const int Matcher::min_vector_size(const BasicType bt) { } // Vector ideal reg corresponding to specidied size in bytes -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize >= size, ""); switch(size) { case 4: return Op_VecS; @@ -1401,7 +1401,7 @@ const int Matcher::vector_ideal_reg(int size) { } // Only lowest bits of xmm reg are used for vector shift count. -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { return Op_VecS; } @@ -1804,9 +1804,9 @@ operand cmpOp_vcmppd() %{ instruct ShouldNotReachHere() %{ match(Halt); - format %{ "int3\t# ShouldNotReachHere" %} + format %{ "ud2\t# ShouldNotReachHere" %} ins_encode %{ - __ int3(); + __ ud2(); %} ins_pipe(pipe_slow); %} @@ -10520,3 +10520,161 @@ instruct vxor64B_mem(vecZ dst, vecZ src, memory mem) %{ ins_pipe( pipe_slow ); %} +// --------------------------------- FMA -------------------------------------- + +// a * b + c +instruct vfma2D_reg(vecX a, vecX b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set c (FmaVD c (Binary a b))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed2D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma2D_mem(vecX a, memory b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set c (FmaVD c (Binary a (LoadVector b)))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed2D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + + +// a * b + c +instruct vfma4D_reg(vecY a, vecY b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVD c (Binary a b))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed4D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma4D_mem(vecY a, memory b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVD c (Binary a (LoadVector b)))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed4D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8D_reg(vecZ a, vecZ b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVD c (Binary a b))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed8D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8D_mem(vecZ a, memory b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVD c (Binary a (LoadVector b)))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed8D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma4F_reg(vecX a, vecX b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVF c (Binary a b))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed4F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma4F_mem(vecX a, memory b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVF c (Binary a (LoadVector b)))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed4F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8F_reg(vecY a, vecY b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVF c (Binary a b))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed8F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8F_mem(vecY a, memory b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVF c (Binary a (LoadVector b)))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed8F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma16F_reg(vecZ a, vecZ b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 16); + match(Set c (FmaVF c (Binary a b))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed16F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma16F_mem(vecZ a, memory b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 16); + match(Set c (FmaVF c (Binary a (LoadVector b)))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed16F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index e82361ba810..2914c277891 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -290,7 +290,7 @@ static int pre_call_resets_size() { if (C->in_24_bit_fp_mode()) { size += 6; // fldcw } - if (C->max_vector_size() > 16) { + if (VM_Version::supports_vzeroupper()) { size += 3; // vzeroupper } return size; @@ -1884,7 +1884,6 @@ encode %{ } %} - enc_class pre_call_resets %{ // If method sets FPU control word restore it here debug_only(int off0 = cbuf.insts_size()); @@ -1892,12 +1891,10 @@ encode %{ MacroAssembler _masm(&cbuf); __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } - if (ra_->C->max_vector_size() > 16) { - // Clear upper bits of YMM registers when current compiled code uses - // wide vectors to avoid AVX <-> SSE transition penalty during call. - MacroAssembler _masm(&cbuf); - __ vzeroupper(); - } + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler _masm(&cbuf); + __ vzeroupper(); debug_only(int off1 = cbuf.insts_size()); assert(off1 - off0 == pre_call_resets_size(), "correct size prediction"); %} @@ -13072,7 +13069,7 @@ instruct CallLeafNoFPDirect(method meth) %{ ins_cost(300); format %{ "CALL_LEAF_NOFP,runtime " %} opcode(0xE8); /* E8 cd */ - ins_encode(Java_To_Runtime(meth)); + ins_encode(pre_call_resets, Java_To_Runtime(meth)); ins_pipe( pipe_slow ); %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 99ae5f5f738..598c5acf12d 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -536,7 +536,7 @@ source %{ #define __ _masm. static int clear_avx_size() { - return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper + return (VM_Version::supports_vzeroupper()) ? 3: 0; // vzeroupper } // !!!!! Special hack to get all types of calls to specify the byte offset @@ -919,7 +919,7 @@ int MachPrologNode::reloc() const void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const { Compile* C = ra_->C; - if (C->max_vector_size() > 16) { + if (VM_Version::supports_vzeroupper()) { st->print("vzeroupper"); st->cr(); st->print("\t"); } @@ -955,11 +955,9 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const Compile* C = ra_->C; MacroAssembler _masm(&cbuf); - if (C->max_vector_size() > 16) { - // Clear upper bits of YMM registers when current compiled code uses - // wide vectors to avoid AVX <-> SSE transition penalty during call. - __ vzeroupper(); - } + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + __ vzeroupper(); int framesize = C->frame_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); @@ -2092,12 +2090,11 @@ encode %{ enc_class clear_avx %{ debug_only(int off0 = cbuf.insts_size()); - if (ra_->C->max_vector_size() > 16) { - // Clear upper bits of YMM registers when current compiled code uses - // wide vectors to avoid AVX <-> SSE transition penalty during call. - MacroAssembler _masm(&cbuf); - __ vzeroupper(); - } + // Clear upper bits of YMM registers to avoid AVX <-> SSE transition penalty + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler _masm(&cbuf); + __ vzeroupper(); debug_only(int off1 = cbuf.insts_size()); assert(off1 - off0 == clear_avx_size(), "correct size prediction"); %} @@ -12116,7 +12113,7 @@ instruct CallLeafNoFPDirect(method meth) ins_cost(300); format %{ "call_leaf_nofp,runtime " %} - ins_encode(Java_To_Runtime(meth)); + ins_encode(clear_avx, Java_To_Runtime(meth)); ins_pipe(pipe_slow); %} diff --git a/hotspot/src/cpu/zero/vm/bytes_zero.hpp b/hotspot/src/cpu/zero/vm/bytes_zero.hpp index 186f09d6937..9b56c01e586 100644 --- a/hotspot/src/cpu/zero/vm/bytes_zero.hpp +++ b/hotspot/src/cpu/zero/vm/bytes_zero.hpp @@ -36,16 +36,6 @@ typedef union unaligned { class Bytes: AllStatic { public: - // Returns true if the byte ordering used by Java is different - // from the native byte ordering of the underlying machine. - static inline bool is_Java_byte_ordering_different() { -#ifdef VM_LITTLE_ENDIAN - return true; -#else - return false; -#endif - } - // Efficient reading and writing of unaligned unsigned data in // platform-specific byte ordering. static inline u2 get_native_u2(address p){ diff --git a/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp b/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp deleted file mode 100644 index 8cb5e15588f..00000000000 --- a/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007 Red Hat, Inc. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "assembler_zero.inline.hpp" -#include "memory/metaspaceShared.hpp" - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - ShouldNotCallThis(); -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java index 6cd7a4ad8b0..63625cce2a9 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,16 +36,19 @@ import java.util.Map; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; import jdk.tools.jaotc.binformat.elf.JELFRelocObject; +import jdk.tools.jaotc.binformat.macho.JMachORelocObject; +import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; /** * A format-agnostic container class that holds various components of a binary. * *

* This class holds information necessary to create platform-specific binary containers such as - * ELFContainer for Linux and Solaris operating systems or yet-to be created MachOContainer for Mac - * OS or PEContainer for MS Windows operating systems. + * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac OS or PEContainer + * for MS Windows operating systems. * *

* Method APIs provided by this class are used to construct and populate platform-independent @@ -56,6 +59,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; * Methods to record and access code section contents, symbols and relocations are provided. */ public class BinaryContainer implements SymbolTable { + private final OptionValues graalOptions; private final int codeSegmentSize; @@ -257,36 +261,40 @@ public class BinaryContainer implements SymbolTable { * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the * prefix {@code prefix}. It also initializes internal code container, symbol table and * relocation tables. + * + * @param graalOptions */ - public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) { + public BinaryContainer(OptionValues graalOptions, GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) { + this.graalOptions = graalOptions; + this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize; this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment; // read only, code codeContainer = new CodeContainer(".text", this); - extLinkageContainer = new CodeContainer(".hotspot.linkage.plt", this); + extLinkageContainer = new CodeContainer(".hs.plt.linkage", this); // read only, info configContainer = new ReadOnlyDataContainer(".config", this); - metaspaceNamesContainer = new ReadOnlyDataContainer(".metaspace.names", this); + metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this); methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this); - klassesOffsetsContainer = new ReadOnlyDataContainer(".klasses.offsets", this); - klassesDependenciesContainer = new ReadOnlyDataContainer(".klasses.dependencies", this); + klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this); + klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this); headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this)); stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this); codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this); - constantDataContainer = new ReadOnlyDataContainer(".method.constdata", this); + constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this); // needs relocation patching at load time by the loader - methodMetadataContainer = new ReadOnlyDataContainer(".method.metadata", this); + methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this); // writable sections - metaspaceGotContainer = new ByteContainer(".metaspace.got", this); + metaspaceGotContainer = new ByteContainer(".meta.got", this); metadataGotContainer = new ByteContainer(".metadata.got", this); - methodStateContainer = new ByteContainer(".method.state", this); + methodStateContainer = new ByteContainer(".meth.state", this); oopGotContainer = new ByteContainer(".oop.got", this); - extLinkageGOTContainer = new ByteContainer(".hotspot.linkage.got", this); + extLinkageGOTContainer = new ByteContainer(".hs.got.linkage", this); addGlobalSymbols(); @@ -303,17 +311,17 @@ public class BinaryContainer implements SymbolTable { graalHotSpotVMConfig.useCMSGC, graalHotSpotVMConfig.useTLAB, graalHotSpotVMConfig.useBiasedLocking, - TieredAOT.getValue(), + TieredAOT.getValue(graalOptions), graalHotSpotVMConfig.enableContended, graalHotSpotVMConfig.restrictContended, graphBuilderConfig.omitAssertions() }; - int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().shift, - graalHotSpotVMConfig.getKlassEncoding().shift, + int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().getShift(), + graalHotSpotVMConfig.getKlassEncoding().getShift(), graalHotSpotVMConfig.contendedPaddingWidth, graalHotSpotVMConfig.fieldsAllocationStyle, - 1 << graalHotSpotVMConfig.getOopEncoding().alignment, + 1 << graalHotSpotVMConfig.logMinObjAlignment(), graalHotSpotVMConfig.codeSegmentSize, }; // @formatter:on @@ -497,11 +505,20 @@ public class BinaryContainer implements SymbolTable { switch (osName) { case "Linux": case "SunOS": - JELFRelocObject elfso = new JELFRelocObject(this, outputFileName, aotVersion); - elfso.createELFRelocObject(relocationTable, symbolTable.values()); + JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName, aotVersion); + elfobj.createELFRelocObject(relocationTable, symbolTable.values()); + break; + case "Mac OS X": + JMachORelocObject machobj = new JMachORelocObject(this, outputFileName); + machobj.createMachORelocObject(relocationTable, symbolTable.values()); break; default: - throw new InternalError("Unsupported platform: " + osName); + if (osName.startsWith("Windows")) { + JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion); + pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values()); + break; + } else + throw new InternalError("Unsupported platform: " + osName); } } @@ -742,11 +759,11 @@ public class BinaryContainer implements SymbolTable { } /** - * Add constant data as follows. - Adding the data to the method.constdata section + * Add constant data as follows. - Adding the data to the meth.constdata section * * @param data * @param alignment - * @return the offset in the method.constdata of the data + * @return the offset in the meth.constdata of the data */ public int addConstantData(byte[] data, int alignment) { // Get the current length of the metaspaceNameContainer diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java index 12daa9f356f..3d44ab0cf72 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; -import jdk.tools.jaotc.jnilibelf.ELFContainer; +import jdk.tools.jaotc.binformat.Container; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; @@ -41,7 +41,7 @@ import java.util.Arrays; * The method {@code putIntAt} updates the content of {@code contentBytes}. Changes are not * reflected in {@code contentStream}. */ -public class ByteContainer implements ELFContainer { +public class ByteContainer implements Container { /** * {@code ByteBuffer} representation of {@code BinaryContainer}. */ diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java similarity index 87% rename from hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java index b65b6ae8d25..ad2b405ab90 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,9 +21,9 @@ * questions. */ -package jdk.tools.jaotc.jnilibelf; +package jdk.tools.jaotc.binformat; -public interface ELFContainer { +public interface Container { String getContainerName(); diff --git a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java similarity index 65% rename from hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java index eab1f977723..e03870ebd40 100644 --- a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,17 +21,31 @@ * questions. */ -package compiler.testlibrary.rtm.predicate; +package jdk.tools.jaotc.binformat; -import jdk.test.lib.Platform; -import sun.hotspot.cpuinfo.CPUInfo; +/** + * This class represents ia native OS specific Symbol + */ +public abstract class NativeSymbol { -import java.util.function.BooleanSupplier; + /** String table index. */ + private int index; -public class SupportedCPU implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - if (Platform.isPPC()) { return CPUInfo.hasFeature("tcheck"); } - return CPUInfo.hasFeature("rtm"); + public NativeSymbol(int index) { + this.index = index; + } + + /** + * @return the index + */ + public int getIndex() { + return index; + } + + /** + * @index + */ + public void setIndex(int index) { + this.index = index; } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java index ba0f9090ee7..8fbc0dd23a6 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,7 +25,7 @@ package jdk.tools.jaotc.binformat; import java.util.Objects; -import jdk.tools.jaotc.jnilibelf.ELFSymbol; +import jdk.tools.jaotc.binformat.NativeSymbol; public class Symbol { @@ -51,7 +51,7 @@ public class Symbol { private final Kind kind; private ByteContainer section; - private ELFSymbol elfSymbol; + private NativeSymbol nativeSymbol; /** * Create symbol info. @@ -77,12 +77,12 @@ public class Symbol { return name; } - public ELFSymbol getElfSymbol() { - return elfSymbol; + public NativeSymbol getNativeSymbol() { + return nativeSymbol; } - public void setElfSymbol(ELFSymbol elfSymbol) { - this.elfSymbol = elfSymbol; + public void setNativeSymbol(NativeSymbol nativeSym) { + this.nativeSymbol = nativeSym; } public Binding getBinding() { diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java new file mode 100644 index 00000000000..e61176d07e7 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java @@ -0,0 +1,256 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +/** + * + * Support for the creation of Elf Object files. + * Current support is limited to 64 bit x86_64. + * + */ + +public class Elf { + + /** + * Elf64_Ehdr structure defines + */ + public enum Elf64_Ehdr { + e_ident( 0,16), + e_type(16, 2), + e_machine(18, 2), + e_version(20, 4), + e_entry(24, 8), + e_phoff(32, 8), + e_shoff(40, 8), + e_flags(48, 4), + e_ehsize(52, 2), + e_phentsize(54, 2), + e_phnum(56, 2), + e_shentsize(58, 2), + e_shnum(60, 2), + e_shstrndx(62, 2); + + public final int off; + public final int sz; + + Elf64_Ehdr(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 64; + + /** + * Elf64_Ehdr defines + */ + + /** + * e_ident + */ + public static final int EI_MAG0 = 0; + public static final byte ELFMAG0 = 0x7f; + public static final int EI_MAG1 = 1; + public static final byte ELFMAG1 = 0x45; + public static final int EI_MAG2 = 2; + public static final byte ELFMAG2 = 0x4c; + public static final int EI_MAG3 = 3; + public static final byte ELFMAG3 = 0x46; + + public static final int EI_CLASS = 4; + public static final byte ELFCLASS64 = 0x2; + + public static final int EI_DATA = 5; + public static final byte ELFDATA2LSB = 0x1; + + public static final int EI_VERSION = 6; + public static final byte EV_CURRENT = 0x1; + + public static final int EI_OSABI = 7; + public static final byte ELFOSABI_NONE = 0x0; + + /** + * e_type + */ + public static final char ET_REL = 0x1; + + /** + * e_machine + */ + public static final char EM_NONE = 0; + public static final char EM_X86_64 = 62; + public static final char EM_AARCH64 = 183; + + /** + * e_version + */ + // public static final int EV_CURRENT = 1; + + } + + /** + * Elf64_Shdr structure defines + */ + public enum Elf64_Shdr { + sh_name( 0, 4), + sh_type( 4, 4), + sh_flags( 8, 8), + sh_addr(16, 8), + sh_offset(24, 8), + sh_size(32, 8), + sh_link(40, 4), + sh_info(44, 4), + sh_addralign(48, 8), + sh_entsize(56, 8); + + public final int off; + public final int sz; + + Elf64_Shdr(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 64; + + /** + * Elf64_Shdr defines + */ + + /** + * sh_type + */ + public static final int SHT_PROGBITS = 0x1; + public static final int SHT_SYMTAB = 0x2; + public static final int SHT_STRTAB = 0x3; + public static final int SHT_RELA = 0x4; + public static final int SHT_NOBITS = 0x8; + public static final int SHT_REL = 0x9; + + public static final byte SHN_UNDEF = 0x0; + + /** + * sh_flag + */ + public static final int SHF_WRITE = 0x1; + public static final int SHF_ALLOC = 0x2; + public static final int SHF_EXECINSTR = 0x4; + + } + + /** + * Symbol table entry definitions + * + * Elf64_Sym structure defines + */ + public enum Elf64_Sym { + st_name( 0, 4), + st_info( 4, 1), + st_other( 5, 1), + st_shndx( 6, 2), + st_value( 8, 8), + st_size(16, 8); + + public final int off; + public final int sz; + + Elf64_Sym(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + /* ST_BIND is in bits 4-7 of st_info. ST_TYPE is in low 4 bits */ + public static final byte STB_LOCAL = 0x0; + public static final byte STB_GLOBAL = 0x1; + + public static final byte STT_NOTYPE = 0x0; + public static final byte STT_OBJECT = 0x1; + public static final byte STT_FUNC = 0x2; + + public static byte ELF64_ST_INFO(byte bind, byte type) { + return (byte)(((bind) << 4) + ((type) & 0xf)); + } + + } + + /** + * Elf64_Rel structure defines + */ + public enum Elf64_Rel { + r_offset( 0, 8), + r_info( 8, 8); + + public final int off; + public final int sz; + + Elf64_Rel(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + /** + * Relocation types + */ + public static final int R_X86_64_NONE = 0x0; + public static final int R_X86_64_64 = 0x1; + public static final int R_X86_64_PC32 = 0x2; + public static final int R_X86_64_PLT32 = 0x4; + public static final int R_X86_64_GOTPCREL = 0x9; + + } + + /** + * Elf64_Rela structure defines + */ + public enum Elf64_Rela { + r_offset( 0, 8), + r_info( 8, 8), + r_addend(16, 8); + + public final int off; + public final int sz; + + Elf64_Rela(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + public static final int R_X86_64_NONE = 0x0; + public static final int R_X86_64_64 = 0x1; + public static final int R_X86_64_PC32 = 0x2; + public static final int R_X86_64_PLT32 = 0x4; + public static final int R_X86_64_GOTPCREL = 0x9; + + public static long ELF64_R_INFO(int symidx, int type) { + return (((long)symidx << 32) + ((long)type)); + } + + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/Serializer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java similarity index 62% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/Serializer.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java index e921aed6c37..8d7c8e7d41d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/Serializer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,20 +20,24 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.serialize; -import java.io.Flushable; -import java.io.IOException; +package jdk.tools.jaotc.binformat.elf; -import org.graalvm.compiler.salver.writer.DumpWriter; -public interface Serializer extends Flushable { +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; - DumpWriter getWriter(); +public class ElfByteBuffer { - void setWriter(DumpWriter writer); + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + if (ElfTargetInfo.getElfEndian() == Elf64_Ehdr.ELFDATA2LSB) + buf.order(ByteOrder.LITTLE_ENDIAN); + else + buf.order(ByteOrder.BIG_ENDIAN); + return (buf); + } - Serializer serialize(Object obj) throws IOException; - - void reset() throws IOException; } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java new file mode 100644 index 00000000000..03b8682c95e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java @@ -0,0 +1,85 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +import java.io.File; +import java.io.FileOutputStream; + +public class ElfContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public ElfContainer(String fileName, String aotVersion) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("ElfContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("ElfContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + if (bytes == null) return; + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("ElfContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + if (bytes == null) return; + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("ElfContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java new file mode 100644 index 00000000000..e930d5580a3 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java @@ -0,0 +1,78 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfHeader { + ByteBuffer header; + + public ElfHeader() { + header = ElfByteBuffer.allocate(Elf64_Ehdr.totalsize); + + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG0, Elf64_Ehdr.ELFMAG0); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG1, Elf64_Ehdr.ELFMAG1); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG2, Elf64_Ehdr.ELFMAG2); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG3, Elf64_Ehdr.ELFMAG3); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_CLASS, Elf64_Ehdr.ELFCLASS64); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_DATA, Elf64_Ehdr.ELFDATA2LSB); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_VERSION, Elf64_Ehdr.EV_CURRENT); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_OSABI, Elf64_Ehdr.ELFOSABI_NONE); + + header.putChar(Elf64_Ehdr.e_type.off, Elf64_Ehdr.ET_REL); + header.putChar(Elf64_Ehdr.e_machine.off, ElfTargetInfo.getElfArch()); + header.putInt(Elf64_Ehdr.e_version.off, Elf64_Ehdr.EV_CURRENT); + header.putChar(Elf64_Ehdr.e_ehsize.off, (char)Elf64_Ehdr.totalsize); + header.putChar(Elf64_Ehdr.e_shentsize.off, (char)Elf64_Shdr.totalsize); + + } + + // Update header with file offset of first section + public void setSectionOff(int offset) { + header.putLong(Elf64_Ehdr.e_shoff.off, offset); + } + + // Update header with the number of total sections + public void setSectionNum(int count) { + header.putChar(Elf64_Ehdr.e_shnum.off, (char)count); + } + + // Update header with the section index containing the + // string table for section names + public void setSectionStrNdx(int index) { + header.putChar(Elf64_Ehdr.e_shstrndx.off, (char)index); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java similarity index 55% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java index 47a7ca3905e..817648ec65b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,32 +20,32 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.writer; -import java.io.Closeable; -import java.io.Flushable; -import java.io.IOException; +package jdk.tools.jaotc.binformat.elf; + import java.nio.ByteBuffer; +import java.nio.ByteOrder; -public interface DumpWriter extends Closeable, Flushable, AutoCloseable { +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; - DumpWriter write(byte b) throws IOException; +public class ElfRelocEntry { + ByteBuffer entry; - DumpWriter write(byte[] arr) throws IOException; + public ElfRelocEntry(int offset, int symno, int type, int addend) { - DumpWriter write(ByteBuffer buf) throws IOException; + entry = ElfByteBuffer.allocate(Elf64_Rela.totalsize); - DumpWriter write(CharSequence csq) throws IOException; + entry.putLong(Elf64_Rela.r_offset.off, offset); + entry.putLong(Elf64_Rela.r_info.off, Elf64_Rela.ELF64_R_INFO(symno,type)); + entry.putLong(Elf64_Rela.r_addend.off, addend); + } - DumpWriter writeChar(char v) throws IOException; - - DumpWriter writeShort(short v) throws IOException; - - DumpWriter writeInt(int v) throws IOException; - - DumpWriter writeLong(long v) throws IOException; - - DumpWriter writeFloat(float v) throws IOException; - - DumpWriter writeDouble(double v) throws IOException; + public byte[] getArray() { + return entry.array(); + } } + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java new file mode 100644 index 00000000000..0e28a9f384e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java @@ -0,0 +1,81 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.ElfRelocEntry; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfRelocTable { + ArrayList> relocEntries; + + public ElfRelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int type, + int addend) { + + ElfRelocEntry entry = new ElfRelocEntry(offset, + symno, + type, + addend); + relocEntries.get(sectindex).add(entry); + } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + + if (entryList.size() == 0) + return null; + + ByteBuffer relocData = ElfByteBuffer.allocate(entryList.size() * Elf64_Rela.totalsize); + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryList.size(); i++) { + ElfRelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java new file mode 100644 index 00000000000..5b8814a7fa9 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java @@ -0,0 +1,181 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSection { + String name; + ByteBuffer section; + byte [] data; + boolean hasrelocations; + int sectionIndex; + + /** + * String holding section name strings + */ + private static StringBuilder sectNameTab = new StringBuilder(); + + /** + * Keeps track of bytes in section string table since strTabContent.length() + * is number of chars, not bytes. + */ + private static int shStrTabNrOfBytes = 0; + + public ElfSection(String sectName, byte [] sectData, int sectFlags, + int sectType, boolean hasRelocations, int sectIndex) { + + long align; + + section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize); + + // Return all 0's for NULL section + if (sectIndex == 0) { + sectNameTab.append('\0'); + shStrTabNrOfBytes += 1; + data = null; + hasrelocations = false; + sectionIndex = 0; + return; + } + + section.putInt(Elf64_Shdr.sh_name.off, shStrTabNrOfBytes); + sectNameTab.append(sectName).append('\0'); + shStrTabNrOfBytes += (sectName.getBytes().length + 1); + name = sectName; + + section.putInt(Elf64_Shdr.sh_type.off, sectType); + section.putLong(Elf64_Shdr.sh_flags.off, sectFlags); + section.putLong(Elf64_Shdr.sh_addr.off, 0); + section.putLong(Elf64_Shdr.sh_offset.off, 0); + + if (sectName.equals(".shstrtab")) { + section.putLong(Elf64_Shdr.sh_size.off, shStrTabNrOfBytes); + data = sectNameTab.toString().getBytes(); + } + else { + data = sectData; + section.putLong(Elf64_Shdr.sh_size.off, sectData.length); + } + + section.putLong(Elf64_Shdr.sh_entsize.off, 0); + + // Determine the alignment and entrysize + // based on type of section + switch (sectType) { + case Elf64_Shdr.SHT_PROGBITS: + if ((sectFlags & Elf64_Shdr.SHF_EXECINSTR) != 0) + align = 16; + else + align = 4; + break; + case Elf64_Shdr.SHT_SYMTAB: + align = 8; + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Sym.totalsize); + break; + case Elf64_Shdr.SHT_STRTAB: + align = 1; + break; + case Elf64_Shdr.SHT_RELA: + align = 8; + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rela.totalsize); + break; + case Elf64_Shdr.SHT_REL: + align = 8; + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rel.totalsize); + break; + case Elf64_Shdr.SHT_NOBITS: + align = 4; + break; + default: + align = 8; + break; + } + section.putLong(Elf64_Shdr.sh_addralign.off, align); + + hasrelocations = hasRelocations; + sectionIndex = sectIndex; + } + + public String getName() { + return name; + } + + public long getSize() { + return section.getLong(Elf64_Shdr.sh_size.off); + } + + public int getDataAlign() { + return ((int)section.getLong(Elf64_Shdr.sh_addralign.off)); + } + + // Alignment requirements for the Elf64_Shdr structures + public static int getShdrAlign() { + return (4); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setOffset(long offset) { + section.putLong(Elf64_Shdr.sh_offset.off, offset); + } + + public void setLink(int link) { + section.putInt(Elf64_Shdr.sh_link.off, link); + } + + public void setInfo(int info) { + section.putInt(Elf64_Shdr.sh_info.off, info); + } + + public long getOffset() { + return (section.getLong(Elf64_Shdr.sh_offset.off)); + } + + public boolean hasRelocations() { + return hasrelocations; + } + + public int getSectionId() { + return sectionIndex; + } + +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java new file mode 100644 index 00000000000..6a22019f6bf --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java @@ -0,0 +1,57 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSymbol extends NativeSymbol { + ByteBuffer sym; + + public ElfSymbol(int symbolindex, int strindex, byte type, byte bind, + byte sectindex, long offset, long size) { + super(symbolindex); + sym = ElfByteBuffer.allocate(Elf64_Sym.totalsize); + + sym.putInt(Elf64_Sym.st_name.off, strindex); + sym.put(Elf64_Sym.st_info.off, Elf64_Sym.ELF64_ST_INFO(bind, type)); + sym.put(Elf64_Sym.st_other.off, (byte)0); + // Section indexes start at 1 but we manage the index internally + // as 0 relative + sym.putChar(Elf64_Sym.st_shndx.off, (char)(sectindex)); + sym.putLong(Elf64_Sym.st_value.off, offset); + sym.putLong(Elf64_Sym.st_size.off, size); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java new file mode 100644 index 00000000000..4105c152693 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java @@ -0,0 +1,147 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSymtab { + + ArrayListlocalSymbols = new ArrayList(); + ArrayListglobalSymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent = new StringBuilder(); + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes = 0; + + public ElfSymtab() { + symbolCount = 0; + } + + public ElfSymbol addSymbolEntry(String name, byte type, byte bind, + byte secHdrIndex, long offset, long size) { + // Get the current symbol index and append symbol name to string table. + int index; + ElfSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); + localSymbols.add(sym); + } else { + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + // strTabContent.append("_").append(name).append('\0'); + strTabContent.append(name).append('\0'); + // + 1 for null, + 1 for "_" + //strTabNrOfBytes += (name.getBytes().length + 1 + 1); + strTabNrOfBytes += (name.getBytes().length + 1); + + sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); + if ((bind & Elf64_Sym.STB_GLOBAL) != 0) + globalSymbols.add(sym); + else + localSymbols.add(sym); + } + symbolCount++; + return (sym); + } + + // Update the symbol indexes once all symbols have been added. + // This is required since we'll be reordering the symbols in the + // file to be in the order of Local then global. + public void updateIndexes() { + int index = 0; + + // Update the local symbol indexes + for (int i = 0; i < localSymbols.size(); i++ ) { + ElfSymbol sym = localSymbols.get(i); + sym.setIndex(index++); + } + + // Update the global symbol indexes + for (int i = 0; i < globalSymbols.size(); i++ ) { + ElfSymbol sym = globalSymbols.get(i); + sym.setIndex(index++); + } + } + + public int getNumLocalSyms() { return localSymbols.size(); } + public int getNumGlobalSyms() { return globalSymbols.size(); } + + + // Create a single byte array that contains the symbol table entries + public byte[] getSymtabArray() { + int index = 0; + ByteBuffer symtabData = ElfByteBuffer.allocate(symbolCount*Elf64_Sym.totalsize); + byte [] retarray; + + updateIndexes(); + + // Add the local symbols + for (int i = 0; i < localSymbols.size(); i++ ) { + ElfSymbol sym = localSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the global symbols + for (int i = 0; i < globalSymbols.size(); i++ ) { + ElfSymbol sym = globalSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + retarray = symtabData.array(); + + return (retarray); + } + + // Return the string table array + public byte[] getStrtabArray() { + byte [] strs = strTabContent.toString().getBytes(); + return (strs); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java new file mode 100644 index 00000000000..2c9a6a3c4a0 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java @@ -0,0 +1,83 @@ +/* + * 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 jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class ElfTargetInfo { + /** + * Target architecture. + */ + private static final char arch; + + /** + * Architecture endian-ness. + */ + private static final int endian = Elf64_Ehdr.ELFDATA2LSB; + + /** + * Target OS string. + */ + private static String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = Elf64_Ehdr.EM_X86_64; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = Elf64_Ehdr.EM_NONE; + } + + osName = System.getProperty("os.name").toLowerCase(); + if (!osName.equals("linux") && !osName.equals("sunos")) { + System.out.println("Unsupported Operating System " + osName); + osName = "Unknown"; + } + } + + public static char getElfArch() { + return arch; + } + + public static int getElfEndian() { + return endian; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java index 82bac0c7170..e616f9857ec 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -30,6 +30,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import jdk.tools.jaotc.binformat.Container; import jdk.tools.jaotc.binformat.BinaryContainer; import jdk.tools.jaotc.binformat.ByteContainer; import jdk.tools.jaotc.binformat.CodeContainer; @@ -37,36 +38,60 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; import jdk.tools.jaotc.binformat.Relocation; import jdk.tools.jaotc.binformat.Relocation.RelocType; import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; -import jdk.tools.jaotc.jnilibelf.ELFContainer; -import jdk.tools.jaotc.jnilibelf.ELFSymbol; -import jdk.tools.jaotc.jnilibelf.JNIELFContainer; -import jdk.tools.jaotc.jnilibelf.JNIELFRelocation; -import jdk.tools.jaotc.jnilibelf.JNIELFTargetInfo; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; -import jdk.tools.jaotc.jnilibelf.Pointer; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; public class JELFRelocObject { private final BinaryContainer binContainer; - private final JNIELFContainer elfContainer; + private final ElfContainer elfContainer; private final int segmentSize; public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) { this.binContainer = binContainer; - this.elfContainer = new JNIELFContainer(outputFileName, aotVersion); + this.elfContainer = new ElfContainer(outputFileName, aotVersion); this.segmentSize = binContainer.getCodeSegmentSize(); } - private void createByteSection(ByteContainer c, int scnFlags) { + private ElfSection createByteSection(ArrayListsections, + String sectName, + byte [] scnData, + boolean hasRelocs, + int scnFlags, + int scnType) { + + ElfSection sect = new ElfSection(sectName, + scnData, + scnFlags, + scnType, + hasRelocs, + sections.size()); + // Add this section to our list + sections.add(sect); + + return (sect); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, int scnFlags) { + ElfSection sect; + boolean hasRelocs = c.hasRelocations(); byte[] scnData = c.getByteArray(); - int scnType = ELF.SHT_PROGBITS; - boolean zeros = !c.hasRelocations(); + + int scnType = Elf64_Shdr.SHT_PROGBITS; + boolean zeros = hasRelocs; if (zeros) { for (byte b : scnData) { if (b != 0) { @@ -75,30 +100,30 @@ public class JELFRelocObject { } } if (zeros) { - scnType = ELF.SHT_NOBITS; + scnType = Elf64_Shdr.SHT_NOBITS; } } - int sectionId = elfContainer.createSection(c.getContainerName(), scnData, Elf_Type.ELF_T_BYTE, segmentSize, scnType, scnFlags, ELF.SHN_UNDEF, 0); - c.setSectionId(sectionId); - // Clear out code section data to allow for GC - c.clear(); + sect = createByteSection(sections, c.getContainerName(), + scnData, hasRelocs, + scnFlags, scnType); + c.setSectionId(sect.getSectionId()); } - private void createCodeSection(CodeContainer c) { - createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_EXECINSTR); + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR); } - private void createReadOnlySection(ReadOnlyDataContainer c) { - createByteSection(c, ELF.SHF_ALLOC); + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC); } - private void createReadWriteSection(ByteContainer c) { - createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_WRITE); + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE); } /** - * Create an ELF relocatable object using jdk.tools.jaotc.jnilibelf API. + * Create an ELF relocatable object * * @param relocationTable * @param symbols @@ -106,145 +131,171 @@ public class JELFRelocObject { */ public void createELFRelocObject(Map> relocationTable, Collection symbols) throws IOException { // Allocate ELF Header - elfContainer.createELFHeader(ELF.ET_REL); + ElfHeader eh = new ElfHeader(); + + ArrayList sections = new ArrayList(); + + // Create the null section + createByteSection(sections, null, null, false, 0, 0); // Create text section - createCodeSection(binContainer.getCodeContainer()); - createReadOnlySection(binContainer.getMetaspaceNamesContainer()); - createReadOnlySection(binContainer.getKlassesOffsetsContainer()); - createReadOnlySection(binContainer.getMethodsOffsetsContainer()); - createReadOnlySection(binContainer.getKlassesDependenciesContainer()); - createReadWriteSection(binContainer.getMetaspaceGotContainer()); - createReadWriteSection(binContainer.getMetadataGotContainer()); - createReadWriteSection(binContainer.getMethodStateContainer()); - createReadWriteSection(binContainer.getOopGotContainer()); - createReadWriteSection(binContainer.getMethodMetadataContainer()); - createReadOnlySection(binContainer.getStubsOffsetsContainer()); - createReadOnlySection(binContainer.getHeaderContainer().getContainer()); - createReadOnlySection(binContainer.getCodeSegmentsContainer()); - createReadOnlySection(binContainer.getConstantDataContainer()); - createReadOnlySection(binContainer.getConfigContainer()); + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); // createExternalLinkage(); - createCodeSection(binContainer.getExtLinkageContainer()); - createReadWriteSection(binContainer.getExtLinkageGOTContainer()); + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); // Get ELF symbol data from BinaryContainer object's symbol tables - createELFSymbolTables(symbols); + ElfSymtab symtab = createELFSymbolTables(sections, symbols); // Create string table section and symbol table sections in - // that order since symtab section needs to set the index of strtab in sh_link field - int strTabSectionIndex = elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); + // that order since symtab section needs to set the index of + // strtab in sh_link field + ElfSection strTabSection = createByteSection(sections, + ".strtab", + symtab.getStrtabArray(), + false, + 0, + Elf64_Shdr.SHT_STRTAB); - // Now create .symtab section with the symtab data constructed. On Linux, sh_link of symtab - // contains the index of string table its symbols reference and - // sh_info contains the index of first non-local symbol - int scnInfo = elfContainer.getFirstNonLocalSymbolIndex(); - int symTabSectionIndex = elfContainer.createSection(".symtab", getELFSymbolTableData(), Elf_Type.ELF_T_SYM, 8, ELF.SHT_SYMTAB, ELF.SHF_ALLOC, strTabSectionIndex, scnInfo); + // Now create .symtab section with the symtab data constructed. + // On Linux, sh_link of symtab contains the index of string table + // its symbols reference and sh_info contains the index of first + // non-local symbol + ElfSection symTabSection = createByteSection(sections, + ".symtab", + symtab.getSymtabArray(), + false, + 0, + Elf64_Shdr.SHT_SYMTAB); + symTabSection.setLink(strTabSection.getSectionId()); + symTabSection.setInfo(symtab.getNumLocalSyms()); - buildRelocations(relocationTable, symTabSectionIndex); + ElfRelocTable elfRelocTable = createElfRelocTable(sections, + relocationTable); + + createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId()); // Now, finally, after creating all sections, create shstrtab section - elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); + ElfSection shStrTabSection = createByteSection(sections, + ".shstrtab", + null, + false, + 0, + Elf64_Shdr.SHT_STRTAB); + eh.setSectionStrNdx(shStrTabSection.getSectionId()); - // Run elf_update - elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL); + // Update all section offsets and the Elf header section offset + // Write the Header followed by the contents of each section + // and then the section structures (section table). + int file_offset = Elf64_Ehdr.totalsize; - // Run elfUpdate again to write it out. - elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE); - // Finish ELF processing - elfContainer.elfEnd(); + // and round it up + file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) & + ~((sections.get(1).getDataAlign()-1)); + + // Calc file offsets for section data skipping null section + for (int i = 1; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + file_offset = (file_offset + (sect.getDataAlign()-1)) & + ~((sect.getDataAlign()-1)); + sect.setOffset(file_offset); + file_offset += sect.getSize(); + } + + // Align the section table + file_offset = (file_offset + (ElfSection.getShdrAlign()-1)) & + ~((ElfSection.getShdrAlign()-1)); + + // Update the Elf Header with the offset of the first Elf64_Shdr + // and the number of sections. + eh.setSectionOff(file_offset); + eh.setSectionNum(sections.size()); + + // Write out the Header + elfContainer.writeBytes(eh.getArray()); + + // Write out each section contents skipping null section + for (int i = 1; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign()); + } + + // Write out the section table + for (int i = 0; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign()); + } + + elfContainer.close(); } - - private void buildRelocations(Map> relocationTable, final int symTabSectionIndex) { - /* - * Create relocation sections. This needs to be done after symbol table sections were - * created since relocation entries will need indices of sections to which they apply. - */ - createELFRelocationTables(relocationTable); - createAllRelocationSections(new SymTabELFContainer(symTabSectionIndex)); - } - /** * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF * symbol table and ELF symbol table are created from BinaryContainer's symbol info. * * @param symbols */ - private void createELFSymbolTables(Collection symbols) { + private ElfSymtab createELFSymbolTables(ArrayList sections, Collection symbols) { + ElfSymtab symtab = new ElfSymtab(); + // First, create the initial null symbol. This is a local symbol. - elfContainer.createELFSymbolEntry("", 0, 0, ELF.SHN_UNDEF, 0, 0, true); + symtab.addSymbolEntry("", (byte)0, (byte)0, Elf64_Shdr.SHN_UNDEF, 0, 0); // Now create ELF symbol entries for all symbols. for (Symbol symbol : symbols) { // Get the index of section this symbol is defined in. int secHdrIndex = symbol.getSection().getSectionId(); - boolean isLocal = (symbol.getBinding() == Binding.LOCAL); - ELFSymbol elfSymbol = elfContainer.createELFSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), secHdrIndex, symbol.getSize(), symbol.getOffset(), isLocal); - symbol.setElfSymbol(elfSymbol); + ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize()); + symbol.setNativeSymbol((NativeSymbol)elfSymbol); } + return (symtab); } - /** - * Construct ELF symbol data from BinaryContainer object's symbol tables. - * - * @return a byte array containing the symbol table - */ - private byte[] getELFSymbolTableData() { - final int entrySize = JNIELFTargetInfo.sizeOfSymtabEntry(); - - // First, add all local symbols. - List localSymbols = elfContainer.getLocalSymbols(); - List globalSymbols = elfContainer.getGlobalSymbols(); - - int localSymCount = localSymbols.size(); - int globalSymCount = globalSymbols.size(); - byte[] sectionDataArray = new byte[(localSymCount + globalSymCount) * entrySize]; - - for (int i = 0; i < localSymCount; i++) { - ELFSymbol symbol = localSymbols.get(i); - Pointer address = symbol.getAddress(); - address.copyBytesTo(sectionDataArray, entrySize, i * entrySize); - } - - // Next, add all global symbols. - - for (int i = 0; i < globalSymCount; i++) { - ELFSymbol symbol = globalSymbols.get(i); - Pointer address = symbol.getAddress(); - address.copyBytesTo(sectionDataArray, entrySize, (localSymCount + i) * entrySize); - } - - return sectionDataArray; - } - - private static int getELFTypeOf(Symbol sym) { + private static byte getELFTypeOf(Symbol sym) { Kind kind = sym.getKind(); if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) { - return ELF.STT_FUNC; + return Elf64_Sym.STT_FUNC; } else if (kind == Symbol.Kind.OBJECT) { - return ELF.STT_OBJECT; + return Elf64_Sym.STT_OBJECT; } - return ELF.STT_NOTYPE; + return Elf64_Sym.STT_NOTYPE; } - private static int getELFBindOf(Symbol sym) { + private static byte getELFBindOf(Symbol sym) { Binding binding = sym.getBinding(); if (binding == Symbol.Binding.GLOBAL) { - return ELF.STB_GLOBAL; + return Elf64_Sym.STB_GLOBAL; } - return ELF.STB_LOCAL; + return Elf64_Sym.STB_LOCAL; } /** - * Construct ELF relocation section data from BinaryContainer object's relocation tables. + * Construct a Elf relocation table from BinaryContainer object's relocation tables. * + * @param sections * @param relocationTable */ - private void createELFRelocationTables(Map> relocationTable) { + private ElfRelocTable createElfRelocTable(ArrayList sections, + Map> relocationTable) { + + ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size()); /* - * For each of the symbols with associated relocation records, create an ELF relocation + * For each of the symbols with associated relocation records, create a Elf relocation * entry. */ for (Map.Entry> entry : relocationTable.entrySet()) { @@ -252,18 +303,26 @@ public class JELFRelocObject { Symbol symbol = entry.getKey(); for (Relocation reloc : relocs) { - createRelocation(symbol, reloc); + createRelocation(symbol, reloc, elfRelocTable); } } for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { - createRelocation(entry.getKey(), entry.getValue()); + createRelocation(entry.getKey(), entry.getValue(), elfRelocTable); } + + return (elfRelocTable); } - private void createRelocation(Symbol symbol, Relocation reloc) { + private void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) { RelocType relocType = reloc.getType(); + int elfRelocType = getELFRelocationType(relocType); + ElfSymbol sym = (ElfSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; switch (relocType) { case FOREIGN_CALL_DIRECT: @@ -271,85 +330,89 @@ public class JELFRelocObject { case STUB_CALL_DIRECT: case FOREIGN_CALL_INDIRECT_GOT: { // Create relocation entry - int addend = -4; // Size in bytes of the patch location + // System.out.println("getELFRelocationType: PLT relocation type using X86_64_RELOC_BRANCH"); + addend = -4; // Size in bytes of the patch location // Relocation should be applied at the location after call operand - int offset = reloc.getOffset() + reloc.getSize() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + reloc.getSize() + addend; break; } case FOREIGN_CALL_DIRECT_FAR: { // Create relocation entry - int addend = -8; // Size in bytes of the patch location + addend = -8; // Size in bytes of the patch location // Relocation should be applied at the location after call operand // 10 = 2 (jmp [r]) + 8 (imm64) - int offset = reloc.getOffset() + reloc.getSize() + addend - 2; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + reloc.getSize() + addend - 2; break; } case FOREIGN_CALL_INDIRECT: case JAVA_CALL_INDIRECT: case STUB_CALL_INDIRECT: { // Do nothing. - break; + return; } case EXTERNAL_DATA_REFERENCE_FAR: { // Create relocation entry - int addend = -4; // Size of 32-bit address of the GOT + addend = -4; // Size of 32-bit address of the GOT /* * Relocation should be applied before the test instruction to the move instruction. - * reloc.getOffset() points to the test instruction after the instruction that loads + * offset points to the test instruction after the instruction that loads * the address of polling page. So set the offset appropriately. */ - int offset = reloc.getOffset() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + addend; break; } case METASPACE_GOT_REFERENCE: case EXTERNAL_PLT_TO_GOT: case STATIC_STUB_TO_STATIC_METHOD: case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { - int addend = -4; // Size of 32-bit address of the GOT + addend = -4; // Size of 32-bit address of the GOT /* - * Relocation should be applied before the test instruction to the move instruction. - * reloc.getOffset() points to the test instruction after the instruction that loads - * the address of polling page. So set the offset appropriately. + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. */ - int offset = reloc.getOffset() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + addend; break; } case EXTERNAL_GOT_TO_PLT: case LOADTIME_ADDRESS: { // this is load time relocations - elfContainer.createELFRelocationEntry(reloc.getSection(), reloc.getOffset(), elfRelocType, 0, symbol.getElfSymbol()); break; } default: throw new InternalError("Unhandled relocation type: " + relocType); } + elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend); } - // TODO: Populate the mapping of RelocType to ELF relocation types private static int getELFRelocationType(RelocType relocType) { int elfRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH - switch (JNIELFTargetInfo.getELFArch()) { - case ELF.EM_X64_64: + switch (ElfTargetInfo.getElfArch()) { + case Elf64_Ehdr.EM_X86_64: // Return R_X86_64_* entries based on relocType - if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PLT32; + if (relocType == RelocType.FOREIGN_CALL_DIRECT || + relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PLT32; } else if (relocType == RelocType.STUB_CALL_DIRECT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; + elfRelocType = Elf64_Rela.R_X86_64_PC32; } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; - } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_NONE; + elfRelocType = Elf64_Rela.R_X86_64_64; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || + relocType == RelocType.JAVA_CALL_INDIRECT || + relocType == RelocType.STUB_CALL_INDIRECT) { + elfRelocType = Elf64_Rela.R_X86_64_NONE; } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_GOTPCREL; - } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || - relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; - } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; + elfRelocType = Elf64_Rela.R_X86_64_GOTPCREL; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT || + relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PC32; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || + relocType == RelocType.LOADTIME_ADDRESS) { + elfRelocType = Elf64_Rela.R_X86_64_64; } else { assert false : "Unhandled relocation type: " + relocType; } @@ -360,61 +423,26 @@ public class JELFRelocObject { return elfRelocType; } - private void createAllRelocationSections(ELFContainer symtab) { - for (Map.Entry> entry : elfContainer.getRelocTables().entrySet()) { - createRelocationSection(entry.getKey(), entry.getValue(), symtab); - } - } + private void createElfRelocSections(ArrayList sections, + ElfRelocTable elfRelocTable, + int symtabsectidx) { - private void createRelocationSection(ELFContainer container, ArrayList relocations, ELFContainer symtab) { - String secName = container.getContainerName(); - int entrySize = JNIELFTargetInfo.sizeOfRelocEntry(); - int numEntries = relocations.size(); - byte[] sectionDataBytes = new byte[numEntries * entrySize]; + // Grab count before we create new sections + int count = sections.size(); - for (int index = 0; index < relocations.size(); index++) { - Pointer entry = relocations.get(index); - entry.copyBytesTo(sectionDataBytes, entrySize, index * entrySize); - } - String fullSecName; - // If relocDat is non-null create section - if (sectionDataBytes.length > 0) { - int scnType; - Elf_Type dataType; - if (JNIELFTargetInfo.createReloca() == 0) { - scnType = ELF.SHT_REL; - dataType = Elf_Type.ELF_T_REL; - fullSecName = ".rel" + secName; - } else { - scnType = ELF.SHT_RELA; - dataType = Elf_Type.ELF_T_RELA; - fullSecName = ".rela" + secName; + for (int i = 0; i < count; i++) { + if (elfRelocTable.getNumRelocs(i) > 0) { + ElfSection sect = sections.get(i); + String relname = ".rela" + sect.getName(); + ElfSection relocSection = createByteSection(sections, + relname, + elfRelocTable.getRelocData(i), + false, + 0, + Elf64_Shdr.SHT_RELA); + relocSection.setLink(symtabsectidx); + relocSection.setInfo(sect.getSectionId()); } - // assert compareBytes(relocData.toByteArray(), sectionDataBytes) : "******* Bad array - // copy"; - // sh_link holds the index of section header of symbol table associated with this - // relocation table. - // sh_info holds the index of section header to which this relocation table applies - // to. - elfContainer.createSection(fullSecName, sectionDataBytes, dataType, 8, scnType, ELF.SHF_ALLOC, symtab.getSectionId(), container.getSectionId()); - } - } - - private static class SymTabELFContainer implements ELFContainer { - private final int symTabSectionIndex; - - public SymTabELFContainer(int symTabSectionIndex) { - this.symTabSectionIndex = symTabSectionIndex; - } - - @Override - public String getContainerName() { - return ".symtab"; - } - - @Override - public int getSectionId() { - return symTabSectionIndex; } } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java new file mode 100644 index 00000000000..7223c327763 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java @@ -0,0 +1,474 @@ +/* + * 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. + */ + +/* + * + * File Layout generated by JMachORelocObject + * + * MachO Header + * Load Commands + * LC_SEGMENT_64 + * - Sections + * LC_VERSION_MIN_MAX + * LC_SYMTAB + * LC_DYSYMTAB + * Section Data + * Relocation entries + * Symbol table + * + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.section_64; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; +import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64; +import jdk.tools.jaotc.binformat.macho.MachO.version_min_command; +import jdk.tools.jaotc.binformat.macho.MachO.symtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOContainer; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachOSymtab; +import jdk.tools.jaotc.binformat.macho.MachORelocTable; + +public class JMachORelocObject { + + private final BinaryContainer binContainer; + + private final MachOContainer machoContainer; + + private final int segmentSize; + + public JMachORelocObject(BinaryContainer binContainer, String outputFileName) { + this.binContainer = binContainer; + this.machoContainer = new MachOContainer(outputFileName); + this.segmentSize = binContainer.getCodeSegmentSize(); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, String sectName, String segName, int scnFlags) { + + if (c.getByteArray().length == 0) { + // System.out.println("Skipping creation of " + sectName + " section, no data\n"); + } + + MachOSection sect = new MachOSection(sectName, + segName, + c.getByteArray(), + scnFlags, + c.hasRelocations()); + // Add this section to our list + sections.add(sect); + + // Record the section Id (0 relative) + c.setSectionId(sections.size()-1); + + // TODO: Clear out code section data to allow for GC + // c.clear(); + } + + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, /*c.getContainerName()*/ "__text", "__TEXT", + section_64.S_ATTR_PURE_INSTRUCTIONS| + section_64.S_ATTR_SOME_INSTRUCTIONS); + } + + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, c.getContainerName(), "__TEXT", + section_64.S_ATTR_SOME_INSTRUCTIONS); + } + + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + createByteSection(sections, c, c.getContainerName(), "__DATA", section_64.S_REGULAR); + } + + /** + * Create an MachO relocatable object + * + * @param relocationTable + * @param symbols + * @throws IOException throws {@code IOException} as a result of file system access failures. + */ + public void createMachORelocObject(Map> relocationTable, Collection symbols) throws IOException { + // Allocate MachO Header + // with 4 load commands + // LC_SEGMENT_64 + // LC_VERSION_MIN_MACOSX + // LC_SYMTAB + // LC_DYSYMTAB + + MachOHeader mh = new MachOHeader(); + + ArrayList sections = new ArrayList(); + + // Create Sections contained in the main Segment LC_SEGMENT_64 + + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); + + // createExternalLinkage(); + + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); + // Update the Header sizeofcmds size. + // This doesn't include the Header struct size + mh.setCmdSizes(4, segment_command_64.totalsize + + (section_64.totalsize * sections.size()) + + version_min_command.totalsize + + symtab_command.totalsize + + dysymtab_command.totalsize); + + // Initialize file offset for data past commands + int file_offset = mach_header_64.totalsize + mh.getCmdSize(); + // and round it up + file_offset = (file_offset + (sections.get(0).getAlign()-1)) & ~((sections.get(0).getAlign()-1)); + long address = 0; + int segment_offset = file_offset; + + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + file_offset = (file_offset + (sect.getAlign()-1)) & ~((sect.getAlign()-1)); + address = (address + (sect.getAlign()-1)) & ~((sect.getAlign()-1)); + sect.setOffset(file_offset); + sect.setAddr(address); + file_offset += sect.getSize(); + address += sect.getSize(); + } + + // File size for Segment data + int segment_size = file_offset - segment_offset; + + // Create the LC_SEGMENT_64 Segment which contains the MachOSections + MachOSegment seg = new MachOSegment(segment_command_64.totalsize + + (section_64.totalsize * sections.size()), + segment_offset, + segment_size, + sections.size()); + + + MachOVersion vers = new MachOVersion(); + + // Get symbol data from BinaryContainer object's symbol tables + MachOSymtab symtab = createMachOSymbolTables(sections, symbols); + + // Create LC_DYSYMTAB command + MachODySymtab dysymtab = new MachODySymtab(symtab.getNumLocalSyms(), + symtab.getNumGlobalSyms(), + symtab.getNumUndefSyms()); + + // Create the Relocation Tables + MachORelocTable machORelocs = createMachORelocTable(sections, relocationTable, symtab); + // Calculate file offset for relocation data + file_offset = (file_offset + (machORelocs.getAlign()-1)) & ~((machORelocs.getAlign()-1)); + + // Update relocation sizing information in each section + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + if (sect.hasRelocations()) { + int nreloc = machORelocs.getNumRelocs(i); + sect.setReloff(file_offset); + sect.setRelcount(nreloc); + file_offset += (nreloc * reloc_info.totalsize); + } + } + + // Calculate and set file offset for symbol table data + file_offset = (file_offset + (symtab.getAlign()-1)) & ~((symtab.getAlign()-1)); + symtab.setOffset(file_offset); + + + // Write Out Header + machoContainer.writeBytes(mh.getArray()); + // Write out first Segment + machoContainer.writeBytes(seg.getArray()); + // Write out sections within first Segment + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + machoContainer.writeBytes(sect.getArray()); + } + + // Write out LC_VERSION_MIN_MACOSX command + machoContainer.writeBytes(vers.getArray()); + + // Write out LC_SYMTAB command + symtab.calcSizes(); + machoContainer.writeBytes(symtab.getCmdArray()); + + // Write out LC_DYSYMTAB command + machoContainer.writeBytes(dysymtab.getArray()); + + // Write out data associated with each Section + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + machoContainer.writeBytes(sect.getDataArray(), sect.getAlign()); + } + + // Write out the relocation tables for all sections + for (int i = 0; i < sections.size(); i++) { + if (machORelocs.getNumRelocs(i) > 0) + machoContainer.writeBytes(machORelocs.getRelocData(i), machORelocs.getAlign()); + } + + // Write out data associated with LC_SYMTAB + machoContainer.writeBytes(symtab.getDataArray(), symtab.getAlign()); + + machoContainer.close(); + } + + /** + * Construct MachO symbol data from BinaryContainer object's symbol tables. Both dynamic MachO + * symbol table and MachO symbol table are created from BinaryContainer's symbol info. + * + * @param symbols + * @param symtab + */ + private MachOSymtab createMachOSymbolTables(ArrayListsections, + Collection symbols) { + MachOSymtab symtab = new MachOSymtab(); + // First, create the initial null symbol. This is a local symbol. + symtab.addSymbolEntry("", (byte)nlist_64.N_UNDF, (byte)0, (long)0); + + // Now create MachO symbol entries for all symbols. + for (Symbol symbol : symbols) { + int sectionId = symbol.getSection().getSectionId(); + + // Symbol offsets are relative to the section memory addr + long sectionAddr = sections.get(sectionId).getAddr(); + + MachOSymbol machoSymbol = symtab.addSymbolEntry(symbol.getName(), + getMachOTypeOf(symbol), + (byte)sectionId, + symbol.getOffset() + sectionAddr); + symbol.setNativeSymbol((NativeSymbol)machoSymbol); + } + + // Now that all symbols are enterred, update the + // symbol indexes. This is necessary since they will + // be reordered based on local, global and undefined. + symtab.updateIndexes(); + + return (symtab); + } + + private static byte getMachOTypeOf(Symbol sym) { + Kind kind = sym.getKind(); + byte type = nlist_64.N_UNDF; + + // Global or Local + if (sym.getBinding() == Symbol.Binding.GLOBAL) + type = nlist_64.N_EXT; + + // If Function or Data, add section type + if (kind == Symbol.Kind.NATIVE_FUNCTION || + kind == Symbol.Kind.JAVA_FUNCTION || + kind == Symbol.Kind.OBJECT) { + type |= (nlist_64.N_SECT); + } + + return (type); + } + + /** + * Construct a MachO relocation table from BinaryContainer object's relocation tables. + * + * @param sections + * @param relocationTable + * @param symtab + */ + private MachORelocTable createMachORelocTable(ArrayList sections, + Map> relocationTable, + MachOSymtab symtab) { + + MachORelocTable machORelocTable = new MachORelocTable(sections.size()); + /* + * For each of the symbols with associated relocation records, create a MachO relocation + * entry. + */ + for (Map.Entry> entry : relocationTable.entrySet()) { + List relocs = entry.getValue(); + Symbol symbol = entry.getKey(); + + for (Relocation reloc : relocs) { + createRelocation(symbol, reloc, machORelocTable); + } + } + + for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { + createRelocation(entry.getKey(), entry.getValue(), machORelocTable); + } + + return (machORelocTable); + } + + private void createRelocation(Symbol symbol, Relocation reloc, MachORelocTable machORelocTable) { + RelocType relocType = reloc.getType(); + + int machORelocType = getMachORelocationType(relocType); + MachOSymbol sym = (MachOSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int pcrel = 0; + int length = 0; + int isextern = 1; + +/* + System.out.println("reloctype: " + relocType + " size is " + + reloc.getSize() + " offset is " + offset + + " Section Index is " + (sectindex) + + " Symbol Index is " + symno + + " Symbol Name is " + symbol.getName() + "\n"); +*/ + + switch (relocType) { + case FOREIGN_CALL_DIRECT: + case JAVA_CALL_DIRECT: + case STUB_CALL_DIRECT: + case FOREIGN_CALL_INDIRECT_GOT: { + // Create relocation entry + // System.out.println("getMachORelocationType: PLT relocation type using X86_64_RELOC_BRANCH"); + int addend = -4; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + offset = offset + reloc.getSize() + addend; + pcrel = 1; length = 2; + break; + } + case FOREIGN_CALL_DIRECT_FAR: { + // Create relocation entry + int addend = -8; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + // 10 = 2 (jmp [r]) + 8 (imm64) + offset = offset + reloc.getSize() + addend - 2; + pcrel = 0; length = 3; + break; + } + case FOREIGN_CALL_INDIRECT: + case JAVA_CALL_INDIRECT: + case STUB_CALL_INDIRECT: { + // Do nothing. + return; + } + case EXTERNAL_DATA_REFERENCE_FAR: { + // Create relocation entry + int addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to the move instruction. + * offset points to the test instruction after the instruction that loads + * the address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + pcrel = 0; length = 2; + break; + } + case METASPACE_GOT_REFERENCE: + case EXTERNAL_PLT_TO_GOT: + case STATIC_STUB_TO_STATIC_METHOD: + case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { + int addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + pcrel = 1; length = 2; + break; + } + case EXTERNAL_GOT_TO_PLT: + case LOADTIME_ADDRESS: { + // this is load time relocations + pcrel = 0; length = 3; + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + machORelocTable.createRelocationEntry(sectindex, offset, symno, + pcrel, length, isextern, + machORelocType); + } + + private static int getMachORelocationType(RelocType relocType) { + int machORelocType = 0; + switch (MachOTargetInfo.getMachOArch()) { + case mach_header_64.CPU_TYPE_X86_64: + // Return X86_64_RELOC_* entries based on relocType + if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { + machORelocType = reloc_info.X86_64_RELOC_UNSIGNED; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) { + machORelocType = reloc_info.X86_64_RELOC_NONE; + } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { + machORelocType = reloc_info.X86_64_RELOC_GOT; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) { + machORelocType = reloc_info.X86_64_RELOC_UNSIGNED; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + default: + System.out.println("Relocation Type mapping: Unhandled architecture"); + } + return machORelocType; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java new file mode 100644 index 00000000000..752723f25dc --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java @@ -0,0 +1,307 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +/** + * + * Support for the creation of Mach-o Object files. + * Current support is limited to 64 bit x86_64. + * + * File Format Overview: + * + * mach_header + * load_commands + * Typical Mac OSX 64-bit object files have these 4 load_commands + * (LC_SEGMENT_64, LC_SYMTAB, LC_VERSIN_MIN_MACOSX, LC_DYSYMTAB) + * Segments corresponding to load_commands + * (which each include multiple Sections) + */ + +public class MachO { + + /** + * mach_header_64 structure defines + */ + public enum mach_header_64 { + magic( 0, 4), + cputype( 4, 4), + cpusubtype( 8, 4), + filetype(12, 4), + ncmds(16, 4), + sizeofcmds(20, 4), + flags(24, 4), + reserved(28, 4); + + public final int off; + public final int sz; + + mach_header_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 32; + + /** + * mach_header_64 defines + */ + public static final int MH_MAGIC = 0xfeedface; + public static final int MH_MAGIC_64 = 0xfeedfacf; + public static final int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000; + + /** + * filetype + */ + public static final int MH_OBJECT = 0x1; + + /** + * cputype + */ + public static final int CPU_TYPE_ANY = -1; + public static final int CPU_ARCH_ABI64 = 0x1000000; + public static final int CPU_TYPE_X86_64 = 0x1000007; + public static final int CPU_TYPE_ARM64 = 0x100000c; + /** + * cpusubtype + */ + public static final int CPU_SUBTYPE_I386_ALL = 3; + public static final int CPU_SUBTYPE_ARM64_ALL = 0; + public static final int CPU_SUBTYPE_LITTLE_ENDIAN = 0; + public static final int CPU_SUBTYPE_BIG_ENDIAN = 1; + + } + + /** + * segment_command_64 structure defines + */ + public enum segment_command_64 { + cmd( 0, 4), + cmdsize( 4, 4), + segname( 8,16), + vmaddr(24, 8), + vmsize(32, 8), + fileoff(40, 8), + filesize(48, 8), + maxprot(56, 4), + initprot(60, 4), + nsects(64, 4), + flags(68, 4); + + public final int off; + public final int sz; + + segment_command_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 72; + + public static final int LC_SEGMENT_64 = 0x19; + } + + /** + * section_64 structure defines + */ + public enum section_64 { + sectname( 0,16), + segname(16,16), + addr(32, 8), + size(40, 8), + offset(48, 4), + align(52, 4), + reloff(56, 4), + nreloc(60, 4), + flags(64, 4), + reserved1(68, 4), + reserved2(72, 4), + reserved3(76, 4); + + public final int off; + public final int sz; + + section_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 80; + + public static int S_REGULAR = 0x0; + public static int S_CSTRING_LITERALS = 0x2; + public static int S_ATTR_PURE_INSTRUCTIONS = 0x80000000; + public static int S_ATTR_SOME_INSTRUCTIONS = 0x400; + } + + /** + * version_min_command structure defines + */ + public enum version_min_command { + cmd( 0, 4), + cmdsize( 4, 4), + version( 8, 4), + sdk(12, 4); + + public final int off; + public final int sz; + + version_min_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + public static final int LC_VERSION_MIN_MACOSX = 0x24; + public static final int LC_VERSION_MIN_IPHONEOS = 0x25; + } + + /** + * symtab_command structure defines + */ + public enum symtab_command { + cmd( 0, 4), + cmdsize( 4, 4), + symoff( 8, 4), + nsyms(12, 4), + stroff(16, 4), + strsize(20, 4); + + public final int off; + public final int sz; + + symtab_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + public static final int LC_SYMTAB = 0x2; + } + + /** + * Symbol table entry definitions + * + * nlist_64 structure defines + */ + public enum nlist_64 { + n_strx( 0, 4), + n_type( 4, 1), + n_sect( 5, 1), + n_desc( 6, 2), + n_value( 8, 8); + + public final int off; + public final int sz; + + nlist_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + public static final int N_EXT = 0x1; + public static final int N_TYPE = 0xe; + public static final int N_UNDF = 0x0; + public static final int N_SECT = 0xe; + } + + /** + * dysymtab_command structure defines + */ + public enum dysymtab_command { + cmd( 0, 4), + cmdsize( 4, 4), + ilocalsym( 8, 4), + nlocalsym(12, 4), + iextdefsym(16, 4), + nextdefsym(20, 4), + iundefsym(24, 4), + nundefsym(28, 4), + tocoff(32, 4), + ntoc(36, 4), + modtaboff(40, 4), + nmodtab(44, 4), + extrefsymoff(48, 4), + nextrefsyms(52, 4), + indirectsymoff(56, 4), + nindirectsyms(60, 4), + extreloff(64, 4), + nextrel(68, 4), + locreloff(72, 4), + nlocrel(76, 4); + + public final int off; + public final int sz; + + dysymtab_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 80; + + public static final int LC_DYSYMTAB = 0xb; + } + + /** + * relocation_info structure defines + */ + public enum reloc_info { + r_address( 0, 4), + r_relocinfo( 4, 4); + + public final int off; + public final int sz; + + reloc_info(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 8; + + public static final int REL_SYMNUM_MASK = 0xffffff; + public static final int REL_SYMNUM_SHIFT = 0x0; + public static final int REL_PCREL_MASK = 0x1; + public static final int REL_PCREL_SHIFT = 0x18; + public static final int REL_LENGTH_MASK = 0x3; + public static final int REL_LENGTH_SHIFT = 0x19; + public static final int REL_EXTERN_MASK = 0x1; + public static final int REL_EXTERN_SHIFT = 0x1b; + public static final int REL_TYPE_MASK = 0xf; + public static final int REL_TYPE_SHIFT = 0x1c; + + /* reloc_type_x86_64 defines */ + + public static final int X86_64_RELOC_NONE = 0x0; + public static final int X86_64_RELOC_BRANCH = 0x2; + public static final int X86_64_RELOC_GOT = 0x4; + public static final int X86_64_RELOC_GOT_LOAD = 0x3; + public static final int X86_64_RELOC_SIGNED = 0x1; + public static final int X86_64_RELOC_UNSIGNED = 0x0; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java new file mode 100644 index 00000000000..14b75387277 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java @@ -0,0 +1,44 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; + +public class MachOByteBuffer { + + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + if (MachOTargetInfo.getMachOEndian() == + MachO.mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN) + buf.order(ByteOrder.LITTLE_ENDIAN); + else + buf.order(ByteOrder.BIG_ENDIAN); + return (buf); + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java new file mode 100644 index 00000000000..bcb46c368c7 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java @@ -0,0 +1,83 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.io.File; +import java.io.FileOutputStream; + +public class MachOContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public MachOContainer(String fileName) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("MachOContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("MachOContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("MachOContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("MachOContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java new file mode 100644 index 00000000000..4ede3869087 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java @@ -0,0 +1,54 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachODySymtab { + ByteBuffer dysymtab; + + public MachODySymtab(int nlocal, int nglobal, int nundef) { + dysymtab = MachOByteBuffer.allocate(dysymtab_command.totalsize); + + dysymtab.putInt(dysymtab_command.cmd.off, dysymtab_command.LC_DYSYMTAB); + dysymtab.putInt(dysymtab_command.cmdsize.off, dysymtab_command.totalsize); + dysymtab.putInt(dysymtab_command.ilocalsym.off, 0); + dysymtab.putInt(dysymtab_command.nlocalsym.off, nlocal); + dysymtab.putInt(dysymtab_command.iextdefsym.off, nlocal); + dysymtab.putInt(dysymtab_command.nextdefsym.off, nglobal); + dysymtab.putInt(dysymtab_command.iundefsym.off, nlocal+nglobal); + dysymtab.putInt(dysymtab_command.nundefsym.off, nundef); + } + + public byte[] getArray() { + return dysymtab.array(); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java new file mode 100644 index 00000000000..ae50f0186d9 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java @@ -0,0 +1,60 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOHeader { + ByteBuffer header; + + public MachOHeader() { + header = MachOByteBuffer.allocate(mach_header_64.totalsize); + + header.putInt(mach_header_64.magic.off, mach_header_64.MH_MAGIC_64); + header.putInt(mach_header_64.cputype.off, MachOTargetInfo.getMachOArch()); + header.putInt(mach_header_64.cpusubtype.off, MachOTargetInfo.getMachOSubArch()); + header.putInt(mach_header_64.flags.off, 0x2000); + header.putInt(mach_header_64.filetype.off, mach_header_64.MH_OBJECT); + } + + public void setCmdSizes(int ncmds, int sizeofcmds) { + header.putInt(mach_header_64.ncmds.off, ncmds); + header.putInt(mach_header_64.sizeofcmds.off, sizeofcmds); + } + + public int getCmdSize() { + return (header.getInt(mach_header_64.sizeofcmds.off)); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java new file mode 100644 index 00000000000..f32cfda3d78 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java @@ -0,0 +1,65 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachORelocEntry { + ByteBuffer entry; + + public MachORelocEntry(int offset, + int symno, + int pcrel, + int length, + int isextern, + int type) { + + entry = MachOByteBuffer.allocate(reloc_info.totalsize); + + entry.putInt(reloc_info.r_address.off, offset); + + // Encode and store the relocation entry bitfields + entry.putInt(reloc_info.r_relocinfo.off, + ((symno & reloc_info.REL_SYMNUM_MASK) + << reloc_info.REL_SYMNUM_SHIFT) | + ((pcrel & reloc_info.REL_PCREL_MASK) + << reloc_info.REL_PCREL_SHIFT) | + ((length & reloc_info.REL_LENGTH_MASK) + << reloc_info.REL_LENGTH_SHIFT) | + ((isextern & reloc_info.REL_EXTERN_MASK) + << reloc_info.REL_EXTERN_SHIFT) | + ((type & reloc_info.REL_TYPE_MASK) + << reloc_info.REL_TYPE_SHIFT)); + } + + public byte[] getArray() { + return entry.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java new file mode 100644 index 00000000000..196ae4615a8 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java @@ -0,0 +1,89 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachORelocEntry; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachORelocTable { + ArrayList> relocEntries; + int fileOffset; + + public MachORelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int pcrel, + int length, + int isextern, + int type) { + + MachORelocEntry entry = new MachORelocEntry(offset, + symno, + pcrel, + length, + isextern, + type); + relocEntries.get(sectindex).add(entry); + } + + public int getAlign() { + return (4); + } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + + if (entryList.size() == 0) + return null; + + ByteBuffer relocData = MachOByteBuffer.allocate(entryList.size() * reloc_info.totalsize); + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryList.size(); i++) { + MachORelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java new file mode 100644 index 00000000000..890ff91e5ec --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java @@ -0,0 +1,115 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.section_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSection { + ByteBuffer section; + byte [] data; + boolean hasrelocations; + + public MachOSection(String sectName, String segName, byte [] sectData, int sectFlags, boolean hasRelocations) { + section = MachOByteBuffer.allocate(section_64.totalsize); + + // TODO: Hotspot uses long section names. + // They are getting truncated. + // Is this a problem?? + byte[] sectNameBytes = sectName.getBytes(); + int sectNameMax = section_64.sectname.sz < sectNameBytes.length ? + section_64.sectname.sz : sectNameBytes.length; + + for (int i = 0; i < sectNameMax; i++) + section.put(section_64.sectname.off+i, sectNameBytes[i]); + + byte[] segNameBytes = segName.getBytes(); + int segNameMax = section_64.segname.sz < segNameBytes.length ? + section_64.segname.sz : segNameBytes.length; + + for (int i = 0; i < segNameMax; i++) + section.put(section_64.segname.off+i, segNameBytes[i]); + + section.putLong(section_64.size.off, sectData.length); + + // For now use 8 byte alignment + section.putInt(section_64.align.off, 3); + + section.putInt(section_64.flags.off, sectFlags); + + data = sectData; + + hasrelocations = hasRelocations; + } + + public long getSize() { + return section.getLong(section_64.size.off); + } + + public int getAlign() { + return (1 << section.getInt(section_64.align.off)); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setAddr(long addr) { + section.putLong(section_64.addr.off, addr); + } + + public long getAddr() { + return (section.getLong(section_64.addr.off)); + } + + public void setOffset(int offset) { + section.putInt(section_64.offset.off, offset); + } + + public int getOffset() { + return (section.getInt(section_64.offset.off)); + } + + public void setReloff(int offset) { + section.putInt(section_64.reloff.off, offset); + } + + public void setRelcount(int count) { + section.putInt(section_64.nreloc.off, count); + } + + public boolean hasRelocations() { + return hasrelocations; + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java new file mode 100644 index 00000000000..3f588512783 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java @@ -0,0 +1,56 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSegment { + ByteBuffer segment; + + public MachOSegment(int size, int fileoff, int filesize, int nsects) { + segment = MachOByteBuffer.allocate(segment_command_64.totalsize); + + segment.putInt(segment_command_64.cmd.off, segment_command_64.LC_SEGMENT_64); + segment.putInt(segment_command_64.cmdsize.off, size); + segment.putInt(segment_command_64.maxprot.off, 7); + segment.putInt(segment_command_64.initprot.off, 7); + segment.putInt(segment_command_64.nsects.off, nsects); + segment.putInt(segment_command_64.flags.off, 0); + segment.putLong(segment_command_64.vmaddr.off, 0); + segment.putLong(segment_command_64.vmsize.off, filesize); + segment.putLong(segment_command_64.fileoff.off, fileoff); + segment.putLong(segment_command_64.filesize.off, filesize); + } + + public byte[] getArray() { + return segment.array(); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java new file mode 100644 index 00000000000..7c4444d9cab --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java @@ -0,0 +1,54 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSymbol extends NativeSymbol { + ByteBuffer sym; + + public MachOSymbol(int symbolindex, int strindex, byte type, byte sectindex, long offset) { + super(symbolindex); + sym = MachOByteBuffer.allocate(nlist_64.totalsize); + + sym.putInt(nlist_64.n_strx.off, strindex); + sym.put(nlist_64.n_type.off, type); + // Section indexes start at 1 but we manage the index internally + // as 0 relative + sym.put(nlist_64.n_sect.off, (byte)(sectindex+1)); + sym.putChar(nlist_64.n_desc.off, (char )0); + sym.putLong(nlist_64.n_value.off, offset); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java new file mode 100644 index 00000000000..be24bc83cd8 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java @@ -0,0 +1,211 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.symtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachOSymbol; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSymtab { + + /** + * ByteBuffer holding the LC_SYMTAB command contents + */ + ByteBuffer symtabCmd; + + /** + * ByteBuffer holding the symbol table entries and strings + */ + ByteBuffer symtabData; + + int symtabDataSize; + + ArrayListlocalSymbols = new ArrayList(); + ArrayListglobalSymbols = new ArrayList(); + ArrayListundefSymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent = new StringBuilder(); + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes = 0; + + public MachOSymtab() { + symtabCmd = MachOByteBuffer.allocate(symtab_command.totalsize); + + symtabCmd.putInt(symtab_command.cmd.off, symtab_command.LC_SYMTAB); + symtabCmd.putInt(symtab_command.cmdsize.off, symtab_command.totalsize); + + symbolCount = 0; + + } + + public int getAlign() { + return (4); + } + + public MachOSymbol addSymbolEntry(String name, byte type, byte secHdrIndex, long offset) { + // Get the current symbol index and append symbol name to string table. + int index; + MachOSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset); + localSymbols.add(sym); + } else { + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + strTabContent.append("_").append(name).append('\0'); + // + 1 for null, + 1 for "_" + strTabNrOfBytes += (name.getBytes().length + 1 + 1); + + sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset); + switch (type) { + case nlist_64.N_EXT: + undefSymbols.add(sym); + break; + case nlist_64.N_SECT: + case nlist_64.N_UNDF: // null symbol + localSymbols.add(sym); + break; + case nlist_64.N_SECT|nlist_64.N_EXT: + globalSymbols.add(sym); + break; + default: + System.out.println("Unsupported Symbol type " + type); + break; + } + } + symbolCount++; + return (sym); + } + + public void setOffset(int symoff) { + symtabCmd.putInt(symtab_command.symoff.off, symoff); + } + + // Update the symbol indexes once all symbols have been added. + // This is required since we'll be reordering the symbols in the + // file to be in the order of Local, global and Undefined. + public void updateIndexes() { + int index = 0; + + // Update the local symbol indexes + for (int i = 0; i < localSymbols.size(); i++ ) { + MachOSymbol sym = localSymbols.get(i); + sym.setIndex(index++); + } + + // Update the global symbol indexes + for (int i = 0; i < globalSymbols.size(); i++ ) { + MachOSymbol sym = globalSymbols.get(i); + sym.setIndex(index++); + } + + // Update the undefined symbol indexes + for (int i = index; i < undefSymbols.size(); i++ ) { + MachOSymbol sym = undefSymbols.get(i); + sym.setIndex(index++); + } + } + + // Update LC_SYMTAB command fields based on the number of symbols added + // return the file size taken up by symbol table entries and strings + public int calcSizes() { + int stroff; + + stroff = symtabCmd.getInt(symtab_command.symoff.off) + (nlist_64.totalsize * symbolCount); + symtabCmd.putInt(symtab_command.nsyms.off, symbolCount); + symtabCmd.putInt(symtab_command.stroff.off, stroff); + symtabCmd.putInt(symtab_command.strsize.off, strTabNrOfBytes); + symtabDataSize = (nlist_64.totalsize * symbolCount) + strTabNrOfBytes; + + return (symtabDataSize); + } + + public int getNumLocalSyms() { return localSymbols.size(); } + public int getNumGlobalSyms() { return globalSymbols.size(); } + public int getNumUndefSyms() { return undefSymbols.size(); } + + public byte[] getCmdArray() { + return symtabCmd.array(); + } + + // Create a single byte array that contains the symbol table entries + // and string table + public byte[] getDataArray() { + int index = 0; + symtabData = MachOByteBuffer.allocate(symtabDataSize); + byte [] retarray; + + // Add the local symbols + for (int i = 0; i < localSymbols.size(); i++ ) { + MachOSymbol sym = localSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the global symbols + for (int i = 0; i < globalSymbols.size(); i++ ) { + MachOSymbol sym = globalSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the undefined symbols + for (int i = 0; i < undefSymbols.size(); i++ ) { + MachOSymbol sym = undefSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + + // Add the stringtable + byte [] strs = strTabContent.toString().getBytes(); + symtabData.put(strs); + + retarray = symtabData.array(); + + return (retarray); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java new file mode 100644 index 00000000000..1a0a199d499 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java @@ -0,0 +1,87 @@ +/* + * 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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class MachOTargetInfo { + /** + * Target architecture and subtype. + */ + private static final int arch; + private static final int subarch; + + /** + * Architecture endian-ness. + */ + private static final int endian = mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN; + + /** + * Target OS string. + */ + private static final String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = mach_header_64.CPU_TYPE_X86_64; + subarch = mach_header_64.CPU_SUBTYPE_I386_ALL; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = mach_header_64.CPU_TYPE_ANY; + subarch = 0; + } + + osName = System.getProperty("os.name").toLowerCase(); + } + + public static int getMachOArch() { + return arch; + } + + public static int getMachOSubArch() { + return subarch; + } + + public static int getMachOEndian() { + return endian; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java new file mode 100644 index 00000000000..57475aeb0eb --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java @@ -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 jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.version_min_command; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOVersion { + ByteBuffer version; + + public MachOVersion() { + version = MachOByteBuffer.allocate(version_min_command.totalsize); + + version.putInt(version_min_command.cmd.off, version_min_command.LC_VERSION_MIN_MACOSX); + version.putInt(version_min_command.cmdsize.off, version_min_command.totalsize); + version.putInt(version_min_command.version.off, (10 << 16) | (10 << 8)); /* MacOSX 10.10 */ + version.putInt(version_min_command.sdk.off, 0); /* N/A SDK */ + } + + public byte[] getArray() { + return version.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java new file mode 100644 index 00000000000..a5f47f03cd1 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java @@ -0,0 +1,422 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.Container; +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; + +public class JPECoffRelocObject { + + private final BinaryContainer binContainer; + + private final PECoffContainer pecoffContainer; + + private final int segmentSize; + + public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) { + this.binContainer = binContainer; + this.pecoffContainer = new PECoffContainer(outputFileName, aotVersion); + this.segmentSize = binContainer.getCodeSegmentSize(); + } + + private PECoffSection createByteSection(ArrayListsections, + String sectName, + byte [] scnData, + boolean hasRelocs, + int scnFlags) { + + PECoffSection sect = new PECoffSection(sectName, + scnData, + scnFlags, + hasRelocs, + sections.size()); + // Add this section to our list + sections.add(sect); + + return (sect); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, int scnFlags) { + PECoffSection sect; + boolean hasRelocs = c.hasRelocations(); + byte[] scnData = c.getByteArray(); + + sect = createByteSection(sections, c.getContainerName(), + scnData, hasRelocs, + scnFlags); + + c.setSectionId(sect.getSectionId()); + } + + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_16BYTES | + IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE); + } + + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_16BYTES | + IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA); + } + + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_8BYTES; + + if (c.getByteArray().length > 0) + scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA; + else + scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA; + + createByteSection(sections, c, scnFlags); + } + + /** + * Create an PECoff relocatable object + * + * @param relocationTable + * @param symbols + * @throws IOException throws {@code IOException} as a result of file system access failures. + */ + public void createPECoffRelocObject(Map> relocationTable, Collection symbols) throws IOException { + ArrayList sections = new ArrayList(); + + // Create text section + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); + + // createExternalLinkage(); + + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); + + // Allocate PECoff Header + PECoffHeader header = new PECoffHeader(); + + // Get PECoff symbol data from BinaryContainer object's symbol tables + PECoffSymtab symtab = createPECoffSymbolTables(sections, symbols); + + // Add Linker Directives Section + createByteSection(sections, ".drectve", + symtab.getDirectiveArray(), false, + IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO | + IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_1BYTES); + + // Create the Relocation Tables + PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable); + + // File Output Order + // + // HEADER (Need address of Symbol Table + symbol count) + // SECTIONS (Need pointer to Section Data, Relocation Table) + // DIRECTIVES + // SYMBOL TABLE + // SYMBOLS + // SECTION DATA + // RELOCATION TABLE + + // Calculate Offset for Symbol table + int file_offset = IMAGE_FILE_HEADER.totalsize + + (IMAGE_SECTION_HEADER.totalsize*sections.size()); + + // Update Header fields + header.setSectionCount(sections.size()); + header.setSymbolCount(symtab.getSymtabCount()); + header.setSymbolOff(file_offset); + + // Calculate file offset for first section + file_offset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) + + symtab.getStrtabSize()); + // And round it up + file_offset = (file_offset + (sections.get(0).getDataAlign()-1)) & + ~((sections.get(0).getDataAlign()-1)); + + // Calc file offsets for section data + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + file_offset = (file_offset + (sect.getDataAlign()-1)) & + ~((sect.getDataAlign()-1)); + sect.setOffset(file_offset); + file_offset += sect.getSize(); + } + + // Update relocation sizing information in each section + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + if (sect.hasRelocations()) { + int nreloc = pecoffRelocs.getNumRelocs(i); + sect.setReloff(file_offset); + sect.setRelcount(nreloc); + // extended relocations add an addition entry + if (nreloc > 0xFFFF) nreloc++; + file_offset += (nreloc * IMAGE_RELOCATION.totalsize); + } + } + + // Write out the Header + pecoffContainer.writeBytes(header.getArray()); + + // Write out the section table + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + pecoffContainer.writeBytes(sect.getArray(), PECoffSection.getShdrAlign()); + } + + // Write out the symbol table and string table + pecoffContainer.writeBytes(symtab.getSymtabArray(), 4); + pecoffContainer.writeBytes(symtab.getStrtabArray(), 1); + + // Write out each section contents + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + pecoffContainer.writeBytes(sect.getDataArray(), sect.getDataAlign()); + } + + // Write out Relocation Tables + for (int i = 0; i < sections.size(); i++) { + if (pecoffRelocs.getNumRelocs(i) > 0) { + pecoffContainer.writeBytes(pecoffRelocs.getRelocData(i)); + } + } + pecoffContainer.close(); + } + + /** + * Construct PECoff symbol data from BinaryContainer object's symbol tables. Both dynamic PECoff + * symbol table and PECoff symbol table are created from BinaryContainer's symbol info. + * + * @param symbols + */ + private PECoffSymtab createPECoffSymbolTables(ArrayList sections, Collection symbols) { + PECoffSymtab symtab = new PECoffSymtab(); + + // First, create the initial null symbol. This is a local symbol. + // symtab.addSymbolEntry("", (byte)0, (byte)0, (byte)0, 0, 0); + + // Now create PECoff symbol entries for all symbols. + for (Symbol symbol : symbols) { + // Get the index of section this symbol is defined in. + int secHdrIndex = symbol.getSection().getSectionId(); + PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize()); + symbol.setNativeSymbol((NativeSymbol)pecoffSymbol); + } + return (symtab); + } + + private static byte getPECoffTypeOf(Symbol sym) { + Kind kind = sym.getKind(); + if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) { + return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION; + } + return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_NONE; + } + + private static byte getPECoffClassOf(Symbol sym) { + Binding binding = sym.getBinding(); + if (binding == Symbol.Binding.GLOBAL) { + return IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL; + } + return IMAGE_SYMBOL.IMAGE_SYM_CLASS_STATIC; + } + + /** + * Construct a PECoff relocation table from BinaryContainer object's relocation tables. + * + * @param sections + * @param relocationTable + */ + private PECoffRelocTable createPECoffRelocTable(ArrayList sections, + Map> relocationTable) { + + PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size()); + /* + * For each of the symbols with associated relocation records, create a PECoff relocation + * entry. + */ + for (Map.Entry> entry : relocationTable.entrySet()) { + List relocs = entry.getValue(); + Symbol symbol = entry.getKey(); + + for (Relocation reloc : relocs) { + createRelocation(symbol, reloc, pecoffRelocTable); + } + } + + for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { + createRelocation(entry.getKey(), entry.getValue(), pecoffRelocTable); + } + + return (pecoffRelocTable); + } + + private void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) { + RelocType relocType = reloc.getType(); + + int pecoffRelocType = getPECoffRelocationType(relocType); + PECoffSymbol sym = (PECoffSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; + + switch (relocType) { + case FOREIGN_CALL_DIRECT: + case JAVA_CALL_DIRECT: + case STUB_CALL_DIRECT: + case FOREIGN_CALL_INDIRECT_GOT: { + // Create relocation entry + addend = -4; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + offset = offset + reloc.getSize() + addend; + break; + } + case FOREIGN_CALL_DIRECT_FAR: { + // Create relocation entry + addend = -8; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + // 10 = 2 (jmp [r]) + 8 (imm64) + offset = offset + reloc.getSize() + addend - 2; + break; + } + case FOREIGN_CALL_INDIRECT: + case JAVA_CALL_INDIRECT: + case STUB_CALL_INDIRECT: { + // Do nothing. + return; + } + case EXTERNAL_DATA_REFERENCE_FAR: { + // Create relocation entry + addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to the move instruction. + * offset points to the test instruction after the instruction that loads + * the address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + break; + } + case METASPACE_GOT_REFERENCE: + case EXTERNAL_PLT_TO_GOT: + case STATIC_STUB_TO_STATIC_METHOD: + case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { + addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + break; + } + case EXTERNAL_GOT_TO_PLT: + case LOADTIME_ADDRESS: { + // this is load time relocations + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + pecoffRelocTable.createRelocationEntry(sectindex, offset, symno, pecoffRelocType); + } + + // Return IMAGE_RELOCATION Type based on relocType + private static int getPECoffRelocationType(RelocType relocType) { + int pecoffRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH + switch (PECoffTargetInfo.getPECoffArch()) { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + if (relocType == RelocType.FOREIGN_CALL_DIRECT || + relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || + relocType == RelocType.JAVA_CALL_INDIRECT || + relocType == RelocType.STUB_CALL_INDIRECT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE; + } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT || + relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || + relocType == RelocType.LOADTIME_ADDRESS) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + default: + System.out.println("Relocation Type mapping: Unhandled architecture"); + } + return pecoffRelocType; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java new file mode 100644 index 00000000000..74f6324742e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java @@ -0,0 +1,200 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +/** + * + * Support for the creation of Coff files. + * Current support is limited to 64 bit x86_64. + * + */ + +public class PECoff { + + /** + * IMAGE_FILE_HEADER structure defines + */ + public enum IMAGE_FILE_HEADER { + Machine( 0, 2), + NumberOfSections( 2, 2), + TimeDateStamp( 4, 4), + PointerToSymbolTable( 8, 4), + NumberOfSymbols(12, 4), + SizeOfOptionalHeader(16, 2), + Characteristics(18, 2); + + public final int off; + public final int sz; + + IMAGE_FILE_HEADER(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 20; + + /** + * IMAGE_FILE_HEADER defines + */ + + /** + * Machine + */ + public static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0; + public static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664; + + } + + /** + * IMAGE_SECTION_HEADER structure defines + */ + public enum IMAGE_SECTION_HEADER { + Name( 0, 8), + PhysicalAddress( 8, 4), + VirtualSize( 8, 4), + VirtualAddress(12, 4), + SizeOfRawData(16, 4), + PointerToRawData(20, 4), + PointerToRelocations(24, 4), + PointerToLinenumbers(28, 4), + NumberOfRelocations(32, 2), + NumberOfLinenumbers(34, 2), + Characteristics(36, 4); + + public final int off; + public final int sz; + + IMAGE_SECTION_HEADER(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 40; + + /** + * IMAGE_SECTION_HEADER defines + */ + + /** + * Characteristics + */ + public static final int IMAGE_SCN_CNT_CODE = 0x20; + public static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40; + public static final int IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x80; + public static final int IMAGE_SCN_LNK_COMDAT = 0x1000; + public static final int IMAGE_SCN_LNK_INFO = 0x200; + public static final int IMAGE_SCN_LNK_REMOVE = 0x800; + + public static final int IMAGE_SCN_ALIGN_1BYTES = 0x100000; + public static final int IMAGE_SCN_ALIGN_2BYTES = 0x200000; + public static final int IMAGE_SCN_ALIGN_4BYTES = 0x300000; + public static final int IMAGE_SCN_ALIGN_8BYTES = 0x400000; + public static final int IMAGE_SCN_ALIGN_16BYTES = 0x500000; + public static final int IMAGE_SCN_ALIGN_MASK = 0xf00000; + public static final int IMAGE_SCN_ALIGN_SHIFT = 20; + + public static final int IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; + + public static final int IMAGE_SCN_MEM_SHARED = 0x10000000; + public static final int IMAGE_SCN_MEM_EXECUTE = 0x20000000; + public static final int IMAGE_SCN_MEM_READ = 0x40000000; + public static final int IMAGE_SCN_MEM_WRITE = 0x80000000; + + } + + /** + * Symbol table entry definitions + * + * IMAGE_SYMBOL structure defines + */ + public enum IMAGE_SYMBOL { + ShortName( 0, 8), + Short( 0, 4), + Long( 4, 4), + Value( 8, 4), + SectionNumber(12, 2), + Type(14, 2), + StorageClass(16, 1), + NumberOfAuxSymbols(17, 1); + + public final int off; + public final int sz; + + IMAGE_SYMBOL(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 18; + + /** + * Type + */ + public static final int IMAGE_SYM_DTYPE_NONE = 0x0; + public static final int IMAGE_SYM_DTYPE_FUNCTION = 0x20; + + /** + * StorageClass + */ + public static final int IMAGE_SYM_CLASS_NULL = 0x0; + public static final int IMAGE_SYM_CLASS_EXTERNAL = 0x2; + public static final int IMAGE_SYM_CLASS_STATIC = 0x3; + public static final int IMAGE_SYM_CLASS_LABEL = 0x6; + + } + + /** + * IMAGE_RELOCATION structure defines + */ + public enum IMAGE_RELOCATION { + VirtualAddress( 0, 4), + SymbolTableIndex( 4, 4), + Type( 8, 2); + + public final int off; + public final int sz; + + IMAGE_RELOCATION(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 10; + + /** + * Relocation types + */ + public static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0; + public static final int IMAGE_REL_AMD64_ADDR32 = 0x2; + public static final int IMAGE_REL_AMD64_ADDR64 = 0x1; + public static final int IMAGE_REL_AMD64_REL32 = 0x4; + public static final int IMAGE_REL_AMD64_REL32_1 = 0x5; + public static final int IMAGE_REL_AMD64_REL32_2 = 0x6; + public static final int IMAGE_REL_AMD64_REL32_3 = 0x7; + public static final int IMAGE_REL_AMD64_REL32_4 = 0x8; + public static final int IMAGE_REL_AMD64_REL32_5 = 0x9; + + } + +} diff --git a/hotspot/test/compiler/cpuflags/predicate/AESSupportPredicate.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java similarity index 70% rename from hotspot/test/compiler/cpuflags/predicate/AESSupportPredicate.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java index c2ac3e24316..e212c6b64d7 100644 --- a/hotspot/test/compiler/cpuflags/predicate/AESSupportPredicate.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -21,18 +21,18 @@ * questions. */ -package compiler.cpuflags.predicate; +package jdk.tools.jaotc.binformat.pecoff; -import sun.hotspot.cpuinfo.CPUInfo; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; -import java.util.function.BooleanSupplier; +public class PECoffByteBuffer { -public class AESSupportPredicate implements BooleanSupplier { - - private static final String AES = "aes"; - - @Override - public boolean getAsBoolean() { - return CPUInfo.getFeatures().contains(AES); + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + // Only support Little Endian on Windows + buf.order(ByteOrder.LITTLE_ENDIAN); + return (buf); } + } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java new file mode 100644 index 00000000000..75158fd219f --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java @@ -0,0 +1,85 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.io.File; +import java.io.FileOutputStream; + +public class PECoffContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public PECoffContainer(String fileName, String aotVersion) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("PECoffContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("PECoffContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + if (bytes == null) return; + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("PECoffContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + if (bytes == null) return; + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("PECoffContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java new file mode 100644 index 00000000000..7d2c84f841d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java @@ -0,0 +1,68 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffHeader { + ByteBuffer header; + + public PECoffHeader() { + header = PECoffByteBuffer.allocate(IMAGE_FILE_HEADER.totalsize); + + header.putChar(IMAGE_FILE_HEADER.Machine.off, IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64); + header.putInt(IMAGE_FILE_HEADER.TimeDateStamp.off, (int)(System.currentTimeMillis()/1000)); + header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, 0); + header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, 0); + header.putChar(IMAGE_FILE_HEADER.SizeOfOptionalHeader.off, (char)0); + header.putChar(IMAGE_FILE_HEADER.Characteristics.off, (char)0); + + } + + // Update header with the number of total sections + public void setSectionCount(int count) { + header.putChar(IMAGE_FILE_HEADER.NumberOfSections.off, (char)count); + } + + // Update header with the number of total symbols + public void setSymbolCount(int count) { + header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, count); + } + + // Update header with the offset of symbol table + public void setSymbolOff(int offset) { + header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, offset); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java similarity index 56% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java index cf4a8824b6d..11284dc77a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,38 +20,30 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.core.common.util; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +package jdk.tools.jaotc.binformat.pecoff; -/** - * Mimic a set implementation with an ArrayList. Beneficial for small sets (compared to - * {@link HashSet}). - */ -public class ArraySet extends ArrayList implements Set { - private static final long serialVersionUID = 4476957522387436654L; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; - public ArraySet() { - super(); +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffRelocEntry { + ByteBuffer entry; + + public PECoffRelocEntry(int offset, int symno, int type) { + + entry = PECoffByteBuffer.allocate(IMAGE_RELOCATION.totalsize); + + entry.putInt(IMAGE_RELOCATION.VirtualAddress.off, offset); + entry.putInt(IMAGE_RELOCATION.SymbolTableIndex.off, symno); + entry.putChar(IMAGE_RELOCATION.Type.off, (char)type); } - public ArraySet(int i) { - super(i); - } - - public ArraySet(Collection c) { - super(c); - } - - @Override - public boolean add(E e) { - // avoid duplicated entries - if (contains(e)) { - return false; - } - return super.add(e); + public byte[] getArray() { + return entry.array(); } } + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java new file mode 100644 index 00000000000..c51b9e8710a --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java @@ -0,0 +1,92 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; +import jdk.tools.jaotc.binformat.pecoff.PECoffRelocEntry; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffRelocTable { + ArrayList> relocEntries; + + public PECoffRelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int type) { + + PECoffRelocEntry entry = new PECoffRelocEntry(offset, + symno, + type); + relocEntries.get(sectindex).add(entry); + } + + public int getAlign() { return (4); } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + int entryCount = entryList.size(); + int allocCount = entryCount; + + if (entryCount == 0) + return null; + + if (entryCount > 0xFFFF) + allocCount++; + + ByteBuffer relocData = PECoffByteBuffer.allocate(allocCount * IMAGE_RELOCATION.totalsize); + + // If number of relocs exceeds 65K, add the real size + // in a dummy first reloc entry + if (entryCount > 0xFFFF) { + PECoffRelocEntry entry = new PECoffRelocEntry(allocCount, 0, 0); + relocData.put(entry.getArray()); + } + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryCount; i++) { + PECoffRelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java new file mode 100644 index 00000000000..0e05fdb830a --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java @@ -0,0 +1,140 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSection { + ByteBuffer section; + byte [] data; + boolean hasrelocations; + int sectionIndex; + int align; + + public PECoffSection(String sectName, byte [] sectData, int sectFlags, + boolean hasRelocations, int sectIndex) { + + section = PECoffByteBuffer.allocate(IMAGE_SECTION_HEADER.totalsize); + + // bug: If JVM.oop.got section is empty, VM exits since JVM.oop.got + // symbol ends up as external forwarded reference. + if (sectData.length == 0) sectData = new byte[8]; + + // Copy only Max allowed bytes to Section Entry + byte [] Name = sectName.getBytes(); + int max = Name.length <= IMAGE_SECTION_HEADER.Name.sz ? + Name.length : IMAGE_SECTION_HEADER.Name.sz; + + section.put(Name, IMAGE_SECTION_HEADER.Name.off, max); + + section.putInt(IMAGE_SECTION_HEADER.VirtualSize.off, 0); + section.putInt(IMAGE_SECTION_HEADER.VirtualAddress.off, 0); + section.putInt(IMAGE_SECTION_HEADER.SizeOfRawData.off, sectData.length); + section.putInt(IMAGE_SECTION_HEADER.PointerToLinenumbers.off, 0); + section.putChar(IMAGE_SECTION_HEADER.NumberOfLinenumbers.off, (char)0); + + section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, sectFlags); + + // Extract alignment from Characteristics field + int alignshift = (sectFlags & IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK) >> + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_SHIFT; + + // Use 8 byte alignment if not specified + if (alignshift == 0) + alignshift = 3; + else + --alignshift; + + align = 1 << alignshift; + + data = sectData; + hasrelocations = hasRelocations; + sectionIndex = sectIndex; + } + + public long getSize() { + return section.getInt(IMAGE_SECTION_HEADER.SizeOfRawData.off); + } + + public int getDataAlign() { + return (align); + } + + // Alignment requirements for the IMAGE_SECTION_HEADER structures + public static int getShdrAlign() { + return (4); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setOffset(long offset) { + section.putInt(IMAGE_SECTION_HEADER.PointerToRawData.off, (int)offset); + } + + public long getOffset() { + return (section.getInt(IMAGE_SECTION_HEADER.PointerToRawData.off)); + } + + public void setReloff(int offset) { + section.putInt(IMAGE_SECTION_HEADER.PointerToRelocations.off, offset); + } + + public void setRelcount(int count) { + // If the number of relocs is larger than 65K, then set + // the overflow bit. The real count will be written to + // the first reloc entry for this section. + if (count > 0xFFFF) { + int flags; + section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)0xFFFF); + flags = section.getInt(IMAGE_SECTION_HEADER.Characteristics.off); + flags |= IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_NRELOC_OVFL; + section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, flags); + } + else { + section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)count); + } + } + + public boolean hasRelocations() { + return hasrelocations; + } + + public int getSectionId() { + return sectionIndex; + } + +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java new file mode 100644 index 00000000000..c305dbe071d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java @@ -0,0 +1,61 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSymbol extends NativeSymbol { + ByteBuffer sym; + + public PECoffSymbol(int symbolindex, int strindex, byte type, byte storageclass, + byte sectindex, long offset, long size) { + super(symbolindex); + sym = PECoffByteBuffer.allocate(IMAGE_SYMBOL.totalsize); + + // We don't use short names + sym.putInt(IMAGE_SYMBOL.Short.off, 0); + + sym.putInt(IMAGE_SYMBOL.Long.off, strindex); + sym.putInt(IMAGE_SYMBOL.Value.off, (int)offset); + + // Section indexes start at 1 but we manage the index internally + // as 0 relative except in this structure + sym.putChar(IMAGE_SYMBOL.SectionNumber.off, (char)(sectindex+1)); + + sym.putChar(IMAGE_SYMBOL.Type.off, (char)type); + sym.put(IMAGE_SYMBOL.StorageClass.off, storageclass); + sym.put(IMAGE_SYMBOL.NumberOfAuxSymbols.off, (byte)0); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java new file mode 100644 index 00000000000..34e0ef73f5e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java @@ -0,0 +1,151 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSymtab { + ArrayListsymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent; + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes; + + /** + * String holding Linker Directives + */ + private StringBuilder directives; + + public PECoffSymtab() { + symbolCount = 0; + strTabContent = new StringBuilder(); + directives = new StringBuilder(); + + // The first 4 bytes of the string table contain + // the length of the table (including this length field). + strTabNrOfBytes = 4; + + // Make room for the 4 byte length field + strTabContent.append('\0').append('\0').append('\0').append('\0'); + + // Linker Directives start with 3 spaces to signify ANSI + directives.append(" "); + } + + public PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass, + byte secHdrIndex, long offset, long size) { + // Get the current symbol index and append symbol name to string table. + int index; + PECoffSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); + symbols.add(sym); + } else { + int nameSize = name.getBytes().length; + + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + // strTabContent.append('_').append(name).append('\0'); + strTabContent.append(name).append('\0'); + strTabNrOfBytes += (nameSize + 1); + + sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); + symbols.add(sym); + if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL) + addDirective(name, type); + } + symbolCount++; + return (sym); + } + + private void addDirective(String name, byte type) { + directives.append("/EXPORT:" + name); + if(type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) { + directives.append(",DATA"); + } + directives.append(" "); + } + + public int getSymtabCount() { + return symbolCount; + } + + public int getStrtabSize() { + return strTabNrOfBytes; + } + + // Return a byte array that contains the symbol table entries + public byte[] getSymtabArray() { + ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount*IMAGE_SYMBOL.totalsize); + symtabData.order(ByteOrder.LITTLE_ENDIAN); + + // copy all symbols + for (int i = 0; i < symbolCount; i++ ) { + PECoffSymbol sym = symbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + return (symtabData.array()); + } + + // Return the string table array + public byte[] getStrtabArray() { + byte [] strs = strTabContent.toString().getBytes(); + + // Update the size of the string table + ByteBuffer buff = ByteBuffer.wrap(strs); + buff.order(ByteOrder.LITTLE_ENDIAN); + buff.putInt(0, strTabNrOfBytes); + + return (strs); + } + + public byte[] getDirectiveArray() { + return (directives.toString().getBytes()); + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java new file mode 100644 index 00000000000..9c40f64733f --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java @@ -0,0 +1,74 @@ +/* + * 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 jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class PECoffTargetInfo { + /** + * Target architecture. + */ + private static final char arch; + + /** + * Target OS string. + */ + private static String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN; + } + + osName = System.getProperty("os.name").toLowerCase(); + if (!osName.contains("windows")) { + System.out.println("Unsupported Operating System " + osName); + osName = "Unknown"; + } + } + + public static char getPECoffArch() { + return arch; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java deleted file mode 100644 index ddad5a018da..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java +++ /dev/null @@ -1,76 +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 jdk.tools.jaotc.jnilibelf; - -/** - * This class represents a {@code Elf32_Sym} or {@code Elf64_Sym} as defined in {@code elf.h}. - */ -public class ELFSymbol { - /** Symbol name. */ - private final String name; - - /** String table index. */ - private final int index; - - /** Native memory address of ELF sym entry. */ - private final Pointer address; - private final boolean isLocal; - - public ELFSymbol(String name, int index, Pointer address, boolean isLocal) { - this.name = name; - this.index = index; - this.address = address; - this.isLocal = isLocal; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @return the index - */ - public int getIndex() { - return index; - } - - /** - * @return the address - */ - public Pointer getAddress() { - return address; - } - - @Override - public String toString() { - return "name=" + name + ", index=" + index + ", address=" + address; - } - - public boolean isLocal() { - return isLocal; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java deleted file mode 100644 index 64d699f0371..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java +++ /dev/null @@ -1,476 +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 jdk.tools.jaotc.jnilibelf; - -import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE; - -import java.io.File; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; - -/** - * A class abstraction of an ELF file. - * - */ -public class JNIELFContainer { - - private String outputFileName; - private File outFile; - private int outFileDesc; - - /** - * Pointer to Elf file. This is the same as struct Elf found in libelf.h - */ - private Pointer elfPtr; - - /** - * Class of the ELF container - one of ELFCLASS32 or ELFCLASS64. - */ - private final int elfClass; - - /** - * Pointer to ELF Header. - */ - private Pointer ehdrPtr; - - /** - * Pointer to Program Header. - */ - private Pointer phdrPtr; - - /** - * String holding .shstrtab contents. - */ - private String shStrTabContent = ""; - - /** - * Map of local symbol indexes to ELF symbol entries. - */ - private List localSymbolIndex = new ArrayList<>(); - - /** - * Map of global symbol indexes to ELF symbol entries. - */ - private List globalSymbolIndex = new ArrayList<>(); - - /** - * String holding .strtab contents. - */ - private StringBuilder strTabContent = new StringBuilder(); - - /** - * Keeps track of nr of bytes in .strtab since strTabContent.length() is number of chars, not - * bytes. - */ - private int strTabNrOfBytes = 0; - - /** - * A hashtable that holds (section-name, relocation-table) pairs. For example, [(".rela.text", - * rela-text-reloc-entries), (".rela.plt", rela-plt-reloc-entries), ...]. - */ - private Map> relocTables = new HashMap<>(); - - /** - * Create reloca; 0 => false and non-zero => true. - */ - private final int createReloca; - - /** - * Construct an ELFContainer in preparation for a disk image with file {@code prefix}. - * - * @param fileName name of ELF file to be created - */ - public JNIELFContainer(String fileName, String aotVersion) { - // Check for version compatibility - if (!JNILibELFAPI.elfshim_version().equals(aotVersion)) { - throw new InternalError("libelfshim version mismatch: " + JNILibELFAPI.elfshim_version() + " vs " + aotVersion); - } - - elfClass = JNIELFTargetInfo.getELFClass(); - createReloca = JNIELFTargetInfo.createReloca(); - outputFileName = fileName; - } - - /** - * Get the local ELF symbol table. - * - * @return local symbol table - */ - public List getLocalSymbols() { - return localSymbolIndex; - } - - /** - * Get the global ELF symbol table. - * - * @return list of global ELF symbol table entries - */ - public List getGlobalSymbols() { - return globalSymbolIndex; - } - - /** - * Get string table content (.strtab). - * - * @return string table content - */ - public String getStrTabContent() { - return strTabContent.toString(); - } - - /** - * Get section header string table content (.shstrtab). - * - * @return section header string table content - */ - public String getShStrTabContent() { - return shStrTabContent; - } - - /** - * Get relocation tables. - * - * @return relocation tables - */ - public Map> getRelocTables() { - return relocTables; - } - - /** - * Get the index of first non-local symbol in symbol table. - * - * @return symbol table index - */ - public int getFirstNonLocalSymbolIndex() { - return localSymbolIndex.size(); - } - - /** - * Create ELF header of type {@code ececType}. - * - * @param type type of ELF executable - */ - public void createELFHeader(int type) { - // Check for version compatibility - if (JNILibELFAPI.elf_version(ELF.EV_CURRENT) == ELF.EV_NONE) { - throw new InternalError("ELF version mismatch"); - } - - outFile = constructRelocFile(outputFileName); - // Open a temporary file for the shared library to be created - // TODO: Revisit file permissions; need to add execute permission - outFileDesc = JNILibELFAPI.open_rw(outFile.getPath()); - - if (outFileDesc == -1) { - System.out.println("Failed to open file " + outFile.getPath() + " to write relocatable object."); - } - - elfPtr = JNILibELFAPI.elf_begin(outFileDesc, LibELF.Elf_Cmd.ELF_C_WRITE.intValue(), new Pointer(0L)); - if (elfPtr == null) { - throw new InternalError("elf_begin failed"); - } - - // Allocate new Ehdr of current architecture class - - ehdrPtr = JNILibELFAPI.gelf_newehdr(elfPtr, elfClass); - - JNILibELFAPI.ehdr_set_data_encoding(ehdrPtr, JNIELFTargetInfo.getELFEndian()); - JNILibELFAPI.set_Ehdr_e_machine(elfClass, ehdrPtr, JNIELFTargetInfo.getELFArch()); - JNILibELFAPI.set_Ehdr_e_type(elfClass, ehdrPtr, type); - JNILibELFAPI.set_Ehdr_e_version(elfClass, ehdrPtr, ELF.EV_CURRENT); - } - - /** - * If the file name has a .so extension, replace it with .o extension. Else just add .o - * extension - * - * @param fileName - * @return File object - */ - private static File constructRelocFile(String fileName) { - File relocFile = new File(fileName); - if (relocFile.exists()) { - if (!relocFile.delete()) { - throw new InternalError("Failed to delete existing " + fileName + " file"); - } - } - return relocFile; - } - - /** - * Create {@code count} number of Program headers. - * - * @param count number of program headers to create - * @return true upon success; false upon failure - */ - public boolean createProgramHeader(int count) { - phdrPtr = JNILibELFAPI.gelf_newphdr(elfPtr, count); - if (phdrPtr == null) { - System.out.println("gelf_newphdr error"); - return false; - } - return true; - } - - /** - * Set program header to be of type self. - * - * @return true - */ - public boolean setProgHdrTypeToSelf() { - // Set program header to be of type self - JNILibELFAPI.phdr_set_type_self(elfClass, ehdrPtr, phdrPtr); - // And thus mark it as dirty so that elfUpdate can recompute the structures - JNILibELFAPI.elf_flagphdr(elfPtr, LibELF.Elf_Cmd.ELF_C_SET.intValue(), LibELF.ELF_F_DIRTY); - // TODO: Error checking; look at the return value of elf_update - // and call elf_errmsg appropriately. - return true; - } - - /** - * Create a section. The corresponding section header and section data are created by calling - * the necessary libelf APIs. The section that is created is inserted into the ELF container. - * - * @param secName name of the section - * @param scnData section data - * @param dataType data type - * @param align section alignment - * @param scnType section type - * @param scnFlags section flags - * @param scnLink sh_link field of Elf{32,64}_Shdr - * @param scnInfo sh_info field of Elf{32,64}_Shdr - * @return section index - */ - public int createSection(String secName, byte[] scnData, Elf_Type dataType, int align, int scnType, int scnFlags, int scnLink, int scnInfo) { - // Create a new section - Pointer scnPtr = JNILibELFAPI.elf_newscn(elfPtr); - if (scnPtr == null) { - throw new InternalError("elf_newscn error"); - } - - // Allocate section data for the section - Pointer scnDataPtr = JNILibELFAPI.elf_newdata(scnPtr); - if (scnDataPtr == null) { - String errMsg = JNILibELFAPI.elf_errmsg(-1); - throw new InternalError("elf_newdata error: " + errMsg); - } - - // Get the pointer to section header associated with the new section - Pointer scnHdrPtr = JNILibELFAPI.elf64_getshdr(scnPtr); - - // Add name of the section to section name string - // If secName is null, point the name to the 0th index - // that holds `\0' - byte[] modScnData; - if (secName.isEmpty()) { - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, 0); - modScnData = scnData; - } else { - if (secName.equals(".shstrtab")) { - // Modify .shstrtab data by inserting '\0' at index 0 - String shstrtabSecName = ".shstrtab" + '\0'; - // Additional byte for the '\0' at position 0 - ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1 + shstrtabSecName.length()); - nbuf.put(0, (byte) 0); - nbuf.position(1); - nbuf.put(scnData); - nbuf.position(scnData.length + 1); - // Add the section name ".shstrtab" to its own data - nbuf.put(shstrtabSecName.getBytes(StandardCharsets.UTF_8)); - modScnData = nbuf.array(); - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, scnData.length + 1); - // Set strtab section index - JNILibELFAPI.set_Ehdr_e_shstrndx(elfClass, ehdrPtr, JNILibELFAPI.elf_ndxscn(scnPtr)); - } else if (secName.equals(".strtab")) { - // Modify strtab section data to insert '\0' at position 0. - // Additional byte for the '\0' at position 0 - ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1); - nbuf.put(0, (byte) 0); - nbuf.position(1); - nbuf.put(scnData); - modScnData = nbuf.array(); - // Set the sh_name - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1); - // Add scnName to stringList - shStrTabContent += secName + '\0'; - } else { - // Set the sh_name - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1); - // Add scnName to stringList - shStrTabContent += secName + '\0'; - modScnData = scnData; - } - } - - final int scnDataBufSize = modScnData.length; - - Pointer scnDataBufPtr = null; - if (scnType != ELF.SHT_NOBITS) { - // Allocate native memory for section data - final long address = UNSAFE.allocateMemory(scnDataBufSize + 1); - scnDataBufPtr = new Pointer(address); - scnDataBufPtr.put(modScnData); - } else { - scnDataBufPtr = new Pointer(0L); - } - - // Set data descriptor fields - JNILibELFAPI.set_Data_d_align(scnDataPtr, align); - JNILibELFAPI.set_Data_d_buf(scnDataPtr, scnDataBufPtr); - JNILibELFAPI.set_Data_d_size(scnDataPtr, scnDataBufSize); - JNILibELFAPI.set_Data_d_off(scnDataPtr, 0); - JNILibELFAPI.set_Data_d_type(scnDataPtr, dataType.intValue()); - JNILibELFAPI.set_Data_d_version(scnDataPtr, ELF.EV_CURRENT); - - JNILibELFAPI.set_Shdr_sh_type(elfClass, scnHdrPtr, scnType); - JNILibELFAPI.set_Shdr_sh_flags(elfClass, scnHdrPtr, scnFlags); - JNILibELFAPI.set_Shdr_sh_entsize(elfClass, scnHdrPtr, 0); // TODO: Is this right?? - JNILibELFAPI.set_Shdr_sh_link(elfClass, scnHdrPtr, scnLink); - JNILibELFAPI.set_Shdr_sh_info(elfClass, scnHdrPtr, scnInfo); - - // Add hash section to section pointer list - int index = JNILibELFAPI.elf_ndxscn(scnPtr); - return index; - } - - /** - * Create an ELF symbol entry for a symbol with the given properties. - * - * @param name name of the section in which symName is referenced - * @param type type of symName - * @param bind binding of symName - * @param secHdrIndex section header index of the section in which symName is referenced - * (st_shndx of ELF symbol entry) - * @param size symName size (st_size of ELF symbol entry) - * @param value symName value (st_value of ELF symbol entry) - * @param isLocal true if symbol is local. - */ - public ELFSymbol createELFSymbolEntry(String name, int type, int bind, int secHdrIndex, int size, int value, boolean isLocal) { - // Get the current symbol index and append symbol name to string table. - int index; - if (name.isEmpty()) { - index = 0; - } else { - // NOTE: The +1 comes from the null symbol! - // We can't trust strTabContent.length() since that is chars (UTF16), keep track of - // bytes on our own. - index = strTabNrOfBytes + 1; - strTabContent.append(name).append('\0'); - strTabNrOfBytes += name.getBytes(StandardCharsets.UTF_8).length + 1; - } - - // Create ELF symbol entry - long address = JNILibELFAPI.create_sym_entry(elfClass, index, type, bind, secHdrIndex, size, value); - if (address == 0) { - throw new InternalError("create_sym_entry failed"); - } - Pointer ptr = new Pointer(address); - - if (isLocal) { - final int localIndex = localSymbolIndex.size(); - ELFSymbol symbol = new ELFSymbol(name, localIndex, ptr, isLocal); - localSymbolIndex.add(symbol); - return symbol; - } else { - final int globalIndex = globalSymbolIndex.size(); - ELFSymbol symbol = new ELFSymbol(name, globalIndex, ptr, isLocal); - globalSymbolIndex.add(symbol); - return symbol; - } - } - - /** - * Create an ELF relocation entry for given symbol {@code name} to section {@code secname}. - * - * @param container the section - * @param offset offset into the section contents at which the relocation needs to be applied - * @param type ELF type of the relocation entry - * @param addend Addend for for relocation of type reloca - */ - public void createELFRelocationEntry(ELFContainer container, int offset, int type, int addend, ELFSymbol elfSymbol) { - // Get the index of the symbol. - int index; - if (elfSymbol.isLocal()) { - index = elfSymbol.getIndex(); - } else { - /* - * For global symbol entries the index will be offset by the number of local symbols - * which will be listed first in the symbol table. - */ - index = elfSymbol.getIndex() + localSymbolIndex.size(); - } - - long address = JNILibELFAPI.create_reloc_entry(elfClass, offset, index, type, addend, createReloca); - if (address == 0) { - throw new InternalError("create_reloc_entry failed"); - } - Pointer ptr = new Pointer(address); - /* - * If section name associated with this symbol is set to undefined i.e., secname is null, - * symIndex is undef i.e., 0. - */ - if (relocTables.get(container) == null) { - // Allocate a new table and add it to the hash table of reloc tables - relocTables.put(container, new ArrayList<>()); - } - - // Add the entry - relocTables.get(container).add(ptr); - } - - /** - * Invokes native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd). - * - * @param cmd command - * @return return value of the native function called - */ - public boolean elfUpdate(LibELF.Elf_Cmd cmd) { - JNILibELFAPI.elf_update(elfPtr, cmd.intValue()); - // TODO: Error checking; look at the return value of elf_update - // and call elf_errmsg appropriately. - return true; - } - - /** - * Wrapper function that invokes int elf_end (Elf *elfPtr). and closes ELF output file - * descriptor - * - * @return true - */ - public boolean elfEnd() { - // Finish ELF processing - JNILibELFAPI.elf_end(elfPtr); - // Close file descriptor - JNILibELFAPI.close(outFileDesc); - return true; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java deleted file mode 100644 index 4c4cffd7abe..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java +++ /dev/null @@ -1,148 +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 jdk.tools.jaotc.jnilibelf; - -/** - * Class that abstracts ELF relocations. - * - */ -public interface JNIELFRelocation { - int R_UNDEF = -1; - - /** - * x86-specific relocation types. - * - */ - public interface I386 { - /* i386 relocs. */ - - int R_386_NONE = 0; /* No reloc */ - int R_386_32 = 1; /* Direct 32 bit */ - int R_386_PC32 = 2; /* PC relative 32 bit */ - int R_386_GOT32 = 3; /* 32 bit GOT entry */ - int R_386_PLT32 = 4; /* 32 bit PLT address */ - int R_386_COPY = 5; /* Copy symbol at runtime */ - int R_386_GLOB_DAT = 6; /* Create GOT entry */ - int R_386_JMP_SLOT = 7; /* Create PLT entry */ - int R_386_RELATIVE = 8; /* Adjust by program base */ - int R_386_GOTOFF = 9; /* 32 bit offset to GOT */ - int R_386_GOTPC = 10; /* 32 bit PC relative offset to GOT */ - int R_386_32PLT = 11; - int R_386_TLS_TPOFF = 14; /* Offset in static TLS block */ - int R_386_TLS_IE = 15; /* Address of GOT entry for static TLS block offset */ - int R_386_TLS_GOTIE = 16; /* GOT entry for static TLS block offset */ - int R_386_TLS_LE = 17; /* Offset relative to static TLS block */ - int R_386_TLS_GD = 18; /* Direct 32 bit for GNU version of general dynamic thread local data */ - int R_386_TLS_LDM = 19; /* - * Direct 32 bit for GNU version of local dynamic thread local data - * in LE code - */ - int R_386_16 = 20; - int R_386_PC16 = 21; - int R_386_8 = 22; - int R_386_PC8 = 23; - int R_386_TLS_GD_32 = 24; /* Direct 32 bit for general dynamic thread local data */ - int R_386_TLS_GD_PUSH = 25; /* Tag for pushl in GD TLS code */ - int R_386_TLS_GD_CALL = 26; /* Relocation for call to __tls_get_addr() */ - int R_386_TLS_GD_POP = 27; /* Tag for popl in GD TLS code */ - int R_386_TLS_LDM_32 = 28; /* Direct 32 bit for local dynamic thread local data in LE code */ - int R_386_TLS_LDM_PUSH = 29; /* Tag for pushl in LDM TLS code */ - int R_386_TLS_LDM_CALL = 30; /* Relocation for call to __tls_get_addr() in LDM code */ - int R_386_TLS_LDM_POP = 31; /* Tag for popl in LDM TLS code */ - int R_386_TLS_LDO_32 = 32; /* Offset relative to TLS block */ - int R_386_TLS_IE_32 = 33; /* GOT entry for negated static TLS block offset */ - int R_386_TLS_LE_32 = 34; /* Negated offset relative to static TLS block */ - int R_386_TLS_DTPMOD32 = 35; /* ID of module containing symbol */ - int R_386_TLS_DTPOFF32 = 36; /* Offset in TLS block */ - int R_386_TLS_TPOFF32 = 37; /* Negated offset in static TLS block */ - int R_386_SIZE32 = 38; /* 32-bit symbol size */ - int R_386_TLS_GOTDESC = 39; /* GOT offset for TLS descriptor. */ - int R_386_TLS_DESC_CALL = 40; /* Marker of call through TLS descriptor for relaxation. */ - int R_386_TLS_DESC = 41; /* - * TLS descriptor containing pointer to code and to argument, - * returning the TLS offset for the symbol. - */ - int R_386_IRELATIVE = 42; /* Adjust indirectly by program base */ - /* Keep this the last entry. */ - int R_386_NUM = 43; - } - - /** - * x86_64-specific relocation types. - */ - public interface X86_64 { - /* AMD x86-64 relocations. */ - int R_X86_64_NONE = 0; /* No reloc */ - int R_X86_64_64 = 1; /* Direct 64 bit */ - int R_X86_64_PC32 = 2; /* PC relative 32 bit signed */ - int R_X86_64_GOT32 = 3; /* 32 bit GOT entry */ - int R_X86_64_PLT32 = 4; /* 32 bit PLT address */ - int R_X86_64_COPY = 5; /* Copy symbol at runtime */ - int R_X86_64_GLOB_DAT = 6; /* Create GOT entry */ - int R_X86_64_JUMP_SLOT = 7; /* Create PLT entry */ - int R_X86_64_RELATIVE = 8; /* Adjust by program base */ - int R_X86_64_GOTPCREL = 9; /* 32 bit signed PC relative offset to GOT */ - int R_X86_64_32 = 10; /* Direct 32 bit zero extended */ - int R_X86_64_32S = 11; /* Direct 32 bit sign extended */ - int R_X86_64_16 = 12; /* Direct 16 bit zero extended */ - int R_X86_64_PC16 = 13; /* 16 bit sign extended pc relative */ - int R_X86_64_8 = 14; /* Direct 8 bit sign extended */ - int R_X86_64_PC8 = 15; /* 8 bit sign extended pc relative */ - int R_X86_64_DTPMOD64 = 16; /* ID of module containing symbol */ - int R_X86_64_DTPOFF64 = 17; /* Offset in module's TLS block */ - int R_X86_64_TPOFF64 = 18; /* Offset in initial TLS block */ - int R_X86_64_TLSGD = 19; /* - * 32 bit signed PC relative offset to two GOT entries for GD - * symbol - */ - int R_X86_64_TLSLD = 20; /* - * 32 bit signed PC relative offset to two GOT entries for LD - * symbol - */ - int R_X86_64_DTPOFF32 = 21; /* Offset in TLS block */ - int R_X86_64_GOTTPOFF = 22; /* - * 32 bit signed PC relative offset to GOT entry for IE symbol - */ - int R_X86_64_TPOFF32 = 23; /* Offset in initial TLS block */ - int R_X86_64_PC64 = 24; /* PC relative 64 bit */ - int R_X86_64_GOTOFF64 = 25; /* 64 bit offset to GOT */ - int R_X86_64_GOTPC32 = 26; /* 32 bit signed pc relative offset to GOT */ - int R_X86_64_GOT64 = 27; /* 64-bit GOT entry offset */ - int R_X86_64_GOTPCREL64 = 28; /* 64-bit PC relative offset to GOT entry */ - int R_X86_64_GOTPC64 = 29; /* 64-bit PC relative offset to GOT */ - int R_X86_64_GOTPLT64 = 30; /* like GOT64, says PLT entry needed */ - int R_X86_64_PLTOFF64 = 31; /* 64-bit GOT relative offset to PLT entry */ - int R_X86_64_SIZE32 = 32; /* Size of symbol plus 32-bit addend */ - int R_X86_64_SIZE64 = 33; /* Size of symbol plus 64-bit addend */ - int R_X86_64_GOTPC32_TLSDESC = 34; /* GOT offset for TLS descriptor. */ - int R_X86_64_TLSDESC_CALL = 35; /* - * Marker for call through TLS descriptor. - */ - int R_X86_64_TLSDESC = 36; /* TLS descriptor. */ - int R_X86_64_IRELATIVE = 37; /* Adjust indirectly by program base */ - int R_X86_64_RELATIVE64 = 38; /* 64-bit adjust by program base */ - - int R_X86_64_NUM = 39; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java deleted file mode 100644 index 8248d6fba29..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java +++ /dev/null @@ -1,127 +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 jdk.tools.jaotc.jnilibelf; - -import java.nio.ByteOrder; - -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; - -/** - * Class that abstracts ELF target details. - * - */ -public class JNIELFTargetInfo { - /** - * ELF Class of the target. - */ - private static final int elfClass; - /** - * Target architecture. - */ - private static final int arch; - /** - * Architecture endian-ness. - */ - private static final int endian; - - /** - * Target OS string. - */ - private static final String osName; - - static { - // Find the target arch details - String archStr = System.getProperty("os.arch").toLowerCase(); - String datamodelStr = System.getProperty("sun.arch.data.model"); - - if (datamodelStr.equals("32")) { - elfClass = ELF.ELFCLASS32; - } else if (datamodelStr.equals("64")) { - elfClass = ELF.ELFCLASS64; - } else { - System.out.println("Failed to discover ELF class!"); - elfClass = ELF.ELFCLASSNONE; - } - - ByteOrder bo = ByteOrder.nativeOrder(); - if (bo == ByteOrder.LITTLE_ENDIAN) { - endian = ELF.ELFDATA2LSB; - } else if (bo == ByteOrder.BIG_ENDIAN) { - endian = ELF.ELFDATA2MSB; - } else { - System.out.println("Failed to discover endian-ness!"); - endian = ELF.ELFDATANONE; - } - - if (archStr.equals("x86")) { - arch = ELF.EM_386; - } else if (archStr.equals("amd64") || archStr.equals("x86_64")) { - arch = ELF.EM_X64_64; - } else if (archStr.equals("sparcv9")) { - arch = ELF.EM_SPARCV9; - } else { - System.out.println("Unsupported architecture " + archStr); - arch = ELF.EM_NONE; - } - - osName = System.getProperty("os.name").toLowerCase(); - } - - public static int getELFArch() { - return arch; - } - - public static int getELFClass() { - return elfClass; - } - - public static int getELFEndian() { - return endian; - } - - public static String getOsName() { - return osName; - } - - public static int createReloca() { - switch (arch) { - case ELF.EM_X64_64: - return 1; - default: - return 0; - } - } - - public static int sizeOfSymtabEntry() { - return JNILibELFAPI.size_of_Sym(elfClass); - } - - public static int sizeOfRelocEntry() { - if (createReloca() == 1) { - return JNILibELFAPI.size_of_Rela(elfClass); - } else { - return JNILibELFAPI.size_of_Rel(elfClass); - } - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java deleted file mode 100644 index 5dc277b16ed..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java +++ /dev/null @@ -1,677 +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 jdk.tools.jaotc.jnilibelf; - -public class JNILibELFAPI { - - static { - System.loadLibrary("jelfshim"); - } - - /** - * Definitions for file open. - */ - public static enum OpenFlags { - O_RDONLY(0x0), - O_WRONLY(0x1), - O_RDWR(0x2), - O_CREAT(0x40); - - private final int intVal; - - private OpenFlags(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - - /** - * Definitions reflecting those in elf.h. - * - */ - public interface ELF { - int EI_NIDENT = 16; - - int EI_CLASS = 4; /* File class byte index */ - int ELFCLASSNONE = 0; /* Invalid class */ - int ELFCLASS32 = 1; /* 32-bit objects */ - int ELFCLASS64 = 2; /* 64-bit objects */ - int ELFCLASSNUM = 3; - - int EI_DATA = 5; /* Data encoding byte index */ - int ELFDATANONE = 0; /* Invalid data encoding */ - int ELFDATA2LSB = 1; /* 2's complement, little endian */ - int ELFDATA2MSB = 2; /* 2's complement, big endian */ - int ELFDATANUM = 3; - - // Legal architecture values for e_machine (add others as needed) - int EM_NONE = 0; /* No machine */ - int EM_SPARC = 2; /* SUN SPARC */ - int EM_386 = 3; /* Intel 80386 */ - int EM_SPARCV9 = 43; /* SPARC v9 64-bit */ - int EM_X64_64 = 62; /* AMD x86-64 architecture */ - - /* Legal values for e_type (object file type). */ - - int ET_NONE = 0; /* No file type */ - int ET_REL = 1; /* Relocatable file */ - int ET_EXEC = 2; /* Executable file */ - int ET_DYN = 3; /* Shared object file */ - int ET_CORE = 4; /* Core file */ - int ET_NUM = 5; /* Number of defined types */ - int ET_LOOS = 0xfe00; /* OS-specific range start */ - int ET_HIOS = 0xfeff; /* OS-specific range end */ - int ET_LOPROC = 0xff00; /* Processor-specific range start */ - int ET_HIPROC = 0xffff; /* Processor-specific range end */ - - /* Legal values for e_version (version). */ - - int EV_NONE = 0; /* Invalid ELF version */ - int EV_CURRENT = 1; /* Current version */ - int EV_NUM = 2; - - /* Legal values for p_type (segment type). */ - - int PT_NULL = 0; /* Program header table entry unused */ - int PT_LOAD = 1; /* Loadable program segment */ - int PT_DYNAMIC = 2; /* Dynamic linking information */ - int PT_INTERP = 3; /* Program interpreter */ - int PT_NOTE = 4; /* Auxiliary information */ - int PT_SHLIB = 5; /* Reserved */ - int PT_PHDR = 6; /* Entry for header table itself */ - int PT_TLS = 7; /* Thread-local storage segment */ - int PT_NUM = 8; /* Number of defined types */ - int PT_LOOS = 0x60000000; /* Start of OS-specific */ - int PT_GNU_EH_FRAME = 0x6474e550; /* GCC .eh_frame_hdr segment */ - int PT_GNU_STACK = 0x6474e551; /* Indicates stack executability */ - int PT_GNU_RELRO = 0x6474e552; /* Read-only after relocation */ - int PT_LOSUNW = 0x6ffffffa; - int PT_SUNWBSS = 0x6ffffffa; /* Sun Specific segment */ - int PT_SUNWSTACK = 0x6ffffffb; /* Stack segment */ - int PT_HISUNW = 0x6fffffff; - int PT_HIOS = 0x6fffffff; /* End of OS-specific */ - int PT_LOPROC = 0x70000000; /* Start of processor-specific */ - int PT_HIPROC = 0x7fffffff; /* End of processor-specific */ - - /* Special section indices. */ - - int SHN_UNDEF = 0; /* Undefined section */ - int SHN_LORESERVE = 0xff00; /* Start of reserved indices */ - int SHN_LOPROC = 0xff00; /* Start of processor-specific */ - int SHN_BEFORE = 0xff00; /* Order section before all others (Solaris). */ - int SHN_AFTER = 0xff01; /* Order section after all others (Solaris). */ - int SHN_HIPROC = 0xff1f; /* End of processor-specific */ - int SHN_LOOS = 0xff20; /* Start of OS-specific */ - int SHN_HIOS = 0xff3f; /* End of OS-specific */ - int SHN_ABS = 0xfff1; /* Associated symbol is absolute */ - int SHN_COMMON = 0xfff2; /* Associated symbol is common */ - int SHN_XINDEX = 0xffff; /* Index is in extra table. */ - int SHN_HIRESERVE = 0xffff; /* End of reserved indices */ - - /* Legal values for sh_type (section type). */ - - int SHT_NULL = 0; /* Section header table entry unused */ - int SHT_PROGBITS = 1; /* Program data */ - int SHT_SYMTAB = 2; /* Symbol table */ - int SHT_STRTAB = 3; /* String table */ - int SHT_RELA = 4; /* Relocation entries with addends */ - int SHT_HASH = 5; /* Symbol hash table */ - int SHT_DYNAMIC = 6; /* Dynamic linking information */ - int SHT_NOTE = 7; /* Notes */ - int SHT_NOBITS = 8; /* Program space with no data (bss) */ - int SHT_REL = 9; /* Relocation entries, no addends */ - int SHT_SHLIB = 10; /* Reserved */ - int SHT_DYNSYM = 11; /* Dynamic linker symbol table */ - int SHT_INIT_ARRAY = 14; /* Array of constructors */ - int SHT_FINI_ARRAY = 15; /* Array of destructors */ - int SHT_PREINIT_ARRAY = 16; /* Array of pre-constructors */ - int SHT_GROUP = 17; /* Section group */ - int SHT_SYMTAB_SHNDX = 18; /* Extended section indeces */ - int SHT_NUM = 19; /* Number of defined types. */ - int SHT_LOOS = 0x60000000; /* Start OS-specific. */ - int SHT_GNU_ATTRIBUTES = 0x6ffffff5; /* Object attributes. */ - int SHT_GNU_HASH = 0x6ffffff6; /* GNU-style hash table. */ - int SHT_GNU_LIBLIST = 0x6ffffff7; /* Prelink library list */ - int SHT_CHECKSUM = 0x6ffffff8; /* Checksum for DSO content. */ - int SHT_LOSUNW = 0x6ffffffa; /* Sun-specific low bound. */ - int SHT_SUNW_move = 0x6ffffffa; - int SHT_SUNW_COMDAT = 0x6ffffffb; - int SHT_SUNW_syminfo = 0x6ffffffc; - int SHT_GNU_verdef = 0x6ffffffd; /* Version definition section. */ - int SHT_GNU_verneed = 0x6ffffffe; /* Version needs section. */ - int SHT_GNU_versym = 0x6fffffff; /* Version symbol table. */ - int SHT_HISUNW = 0x6fffffff; /* Sun-specific high bound. */ - int SHT_HIOS = 0x6fffffff; /* End OS-specific type */ - int SHT_LOPROC = 0x70000000; /* Start of processor-specific */ - int SHT_HIPROC = 0x7fffffff; /* End of processor-specific */ - int SHT_LOUSER = 0x80000000; /* Start of application-specific */ - int SHT_HIUSER = 0x8fffffff; /* End of application-specific */ - - /* Legal values for sh_flags (section flags). */ - - int SHF_WRITE = (1 << 0); /* Writable */ - int SHF_ALLOC = (1 << 1); /* Occupies memory during execution */ - int SHF_EXECINSTR = (1 << 2); /* Executable */ - int SHF_MERGE = (1 << 4); /* Might be merged */ - int SHF_STRINGS = (1 << 5); /* Contains nul-terminated strings */ - int SHF_INFO_LINK = (1 << 6); /* `sh_info' contains SHT index */ - int SHF_LINK_ORDER = (1 << 7); /* Preserve order after combining */ - int SHF_OS_NONCONFORMING = (1 << 8); /* Non-standard OS specific handling required */ - int SHF_GROUP = (1 << 9); /* Section is member of a group. */ - int SHF_TLS = (1 << 10); /* Section hold thread-local data. */ - int SHF_MASKOS = 0x0ff00000; /* OS-specific. */ - int SHF_MASKPROC = 0xf0000000; /* Processor-specific */ - int SHF_ORDERED = (1 << 30); /* Special ordering requirement (Solaris). */ - int SHF_EXCLUDE = (1 << 31); /* - * Section is excluded unless referenced or allocated - * (Solaris). - */ - - /* Legal values for ST_BIND subfield of st_info (symbol binding). */ - - int STB_LOCAL = 0; /* Local symbol */ - int STB_GLOBAL = 1; /* Global symbol */ - int STB_WEAK = 2; /* Weak symbol */ - int STB_NUM = 3; /* Number of defined types. */ - int STB_LOOS = 10; /* Start of OS-specific */ - int STB_GNU_UNIQUE = 10; /* Unique symbol. */ - int STB_HIOS = 12; /* End of OS-specific */ - int STB_LOPROC = 13; /* Start of processor-specific */ - int STB_HIPROC = 15; /* End of processor-specific */ - - /* Legal values for ST_TYPE subfield of st_info (symbol type). */ - - int STT_NOTYPE = 0; /* Symbol type is unspecified */ - int STT_OBJECT = 1; /* Symbol is a data object */ - int STT_FUNC = 2; /* Symbol is a code object */ - int STT_SECTION = 3; /* Symbol associated with a section */ - int STT_FILE = 4; /* Symbol's name is file name */ - int STT_COMMON = 5; /* Symbol is a common data object */ - int STT_TLS = 6; /* Symbol is thread-local data object */ - int STT_NUM = 7; /* Number of defined types. */ - int STT_LOOS = 10; /* Start of OS-specific */ - int STT_GNU_IFUNC = 10; /* Symbol is indirect code object */ - int STT_HIOS = 12; /* End of OS-specific */ - int STT_LOPROC = 13; /* Start of processor-specific */ - int STT_HIPROC = 15; /* End of processor-specific */ - } - - /** - * Definitions reflecting those in libelf.h. - * - */ - public interface LibELF { - - public static enum Elf_Cmd { - ELF_C_NULL("NULL"), /* Nothing, terminate, or compute only. */ - ELF_C_READ("READ"), /* Read .. */ - ELF_C_RDWR("RDWR"), /* Read and write .. */ - ELF_C_WRITE("WRITE"), /* Write .. */ - ELF_C_CLR("CLR"), /* Clear flag. */ - ELF_C_SET("SET"), /* Set flag. */ - ELF_C_FDDONE("FDDONE"), /* - * Signal that file descriptor will not be used anymore. - */ - ELF_C_FDREAD("FDREAD"), /* - * Read rest of data so that file descriptor is not used - * anymore. - */ - /* The following are Linux-only extensions. */ - ELF_C_READ_MMAP("READ_MMAP"), /* Read, but mmap the file if possible. */ - ELF_C_RDWR_MMAP("RDWR_MMAP"), /* Read and write, with mmap. */ - ELF_C_WRITE_MMAP("WRITE_MMAP"), /* Write, with mmap. */ - ELF_C_READ_MMAP_PRIVATE("READ_MMAP_PRIVATE"), /* - * Read, but memory is writable, results - * are not written to the file. - */ - ELF_C_EMPTY("EMPTY"), /* Copy basic file data but not the content. */ - /* The following are SunOS-only enums */ - ELF_C_WRIMAGE("WRIMAGE"), - ELF_C_IMAGE("IMAGE"), - /* Common last entry. */ - ELF_C_NUM("NUM"); - private final int intVal; - private final String name; - - private Elf_Cmd(String cmd) { - name = "ELF_C_" + cmd; - switch (cmd) { - case "NULL": - // ELF_C_NULL has the same enum ordinal on both Linux and SunOS - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NULL.ordinal(); - break; - - case "READ": - // ELF_C_READ has the same enum ordinal on both Linux and SunOS - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ.ordinal(); - break; - - // Enums defined in libelf.h of both Linux and SunOS - // but with different ordinals - case "RDWR": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_RDWR.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "WRITE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRITE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "CLR": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_CLR.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_CLR.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "SET": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_SET.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_SET.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "FDDONE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDDONE.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDDONE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "FDREAD": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDREAD.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDREAD.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "NUM": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NUM.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_NUM.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - // Linux-only Elf_Cmd enums - case "READ_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "RDWR_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "WRITE_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "READ_MMAP_PRIVATE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP_PRIVATE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "EMPTY": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_EMPTY.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - // SunOS-only Elf_Cmd enums - case "WRIMAGE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRIMAGE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - case "IMAGE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_IMAGE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - default: - intVal = -1; - } - } - - public int intValue() { - assert intVal != -1 : "enum " + name + "not supported on " + JNIELFTargetInfo.getOsName(); - return intVal; - } - - public String getName() { - return name; - } - } - - public static enum Elf_Type { - ELF_T_BYTE(0), /* unsigned char */ - ELF_T_ADDR(1), /* Elf32_Addr, Elf64_Addr, ... */ - ELF_T_DYN(2), /* Dynamic section record. */ - ELF_T_EHDR(3), /* ELF header. */ - ELF_T_HALF(4), /* Elf32_Half, Elf64_Half, ... */ - ELF_T_OFF(5), /* Elf32_Off, Elf64_Off, ... */ - ELF_T_PHDR(6), /* Program header. */ - ELF_T_RELA(7), /* Relocation entry with addend. */ - ELF_T_REL(8), /* Relocation entry. */ - ELF_T_SHDR(9), /* Section header. */ - ELF_T_SWORD(10), /* Elf32_Sword, Elf64_Sword, ... */ - ELF_T_SYM(11), /* Symbol record. */ - ELF_T_WORD(12), /* Elf32_Word, Elf64_Word, ... */ - ELF_T_XWORD(13), /* Elf32_Xword, Elf64_Xword, ... */ - ELF_T_SXWORD(14), /* Elf32_Sxword, Elf64_Sxword, ... */ - ELF_T_VDEF(15), /* Elf32_Verdef, Elf64_Verdef, ... */ - ELF_T_VDAUX(16), /* Elf32_Verdaux, Elf64_Verdaux, ... */ - ELF_T_VNEED(17), /* Elf32_Verneed, Elf64_Verneed, ... */ - ELF_T_VNAUX(18), /* Elf32_Vernaux, Elf64_Vernaux, ... */ - ELF_T_NHDR(19), /* Elf32_Nhdr, Elf64_Nhdr, ... */ - ELF_T_SYMINFO(20), /* Elf32_Syminfo, Elf64_Syminfo, ... */ - ELF_T_MOVE(21), /* Elf32_Move, Elf64_Move, ... */ - ELF_T_LIB(22), /* Elf32_Lib, Elf64_Lib, ... */ - ELF_T_GNUHASH(23), /* GNU-style hash section. */ - ELF_T_AUXV(24), /* Elf32_auxv_t, Elf64_auxv_t, ... */ - /* Keep this the last entry. */ - ELF_T_NUM(25); - - private final int intVal; - - private Elf_Type(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - - /* Flags for the ELF structures. */ - int ELF_F_DIRTY = 0x1; - int ELF_F_LAYOUT = 0x4; - int ELF_F_PERMISSIVE = 0x8; - - public static enum Elf_Kind { - ELF_K_NONE(0), /* Unknown. */ - ELF_K_AR(1), /* Archive. */ - ELF_K_COFF(2), /* Stupid old COFF. */ - ELF_K_ELF(3), /* ELF file. */ - /* Keep this the last entry. */ - ELF_K_NUM(4); - private final int intVal; - - private Elf_Kind(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - } - - /** - * Invoke native libelf function unsigned int elf_version (unsigned int v). - * - * @param v version - * @return return value of native call - */ - // Checkstyle: stop method name check - static native int elf_version(int v); - - /** - * Return version recorded in libelfshim. - * - * @return return version string - */ - // Checkstyle: stop method name check - static native String elfshim_version(); - - /** - * Invoke native libelf function Elf *elf_begin (int fildes, Elf_Cmd cmd, Elf *elfPtr). - * - * @param fildes open file descriptor - * @param elfCRead command - * @param elfHdrPtr pointer to ELF header - * @return return value of native call - */ - static native Pointer elf_begin(int fildes, int elfCRead, Pointer elfHdrPtr); - - /** - * Invoke native libelf function elf_end (Elf *elfPtr). - * - * @param elfPtr pointer to ELF header - * @return return value of native call - */ - static native int elf_end(Pointer elfPtr); - - /** - * Invoke native libelf function elf_end (Elf *elfPtr). - * - * @param elfPtr pointer to ELF header - * @return return value of native call - */ - static native int elf_kind(Pointer elfPtr); - - /** - * Invoke native libelf function unsigned int elf_flagphdr (Elf *elf, Elf_Cmd cmd, unsigned int - * flags). - * - * @param elfPtr Pointer to ELF descriptor - * @param cmd command - * @param flags flags - * @return return value of native call - */ - static native int elf_flagphdr(Pointer elfPtr, int cmd, int flags); - - /** - * Invoke native libelf function Elf_Scn *elf_newscn (Elf *elfPtr). - * - * @param elfPtr Elf header pointer - * @return return value of native call - */ - static native Pointer elf_newscn(Pointer elfPtr); - - /** - * Invoke native libelf function Elf_Data *elf_newdata (Elf_Scn *scn). - * - * @param scnPtr pointer to section for which the new data descriptor is to be created - * @return return value of native call - */ - static native Pointer elf_newdata(Pointer scnPtr); - - /** - * Invoke native libelf function Elf64_Shdr *elf64_getshdr (Elf_Scn *scnPtr). - * - * @param scnPtr pointer to section whose header information is to be retrieved - * @return return value of native call - */ - static native Pointer elf64_getshdr(Pointer scnPtr); - - /** - * Invoke native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd). - * - * @param elfPtr Pointer to ELF descriptor - * @param cmd command - * @return return value of native call - */ - static native long elf_update(Pointer elfPtr, int cmd); - - /** - * Invoke native libelf function char *elf_errmsg (int error). - * - * @param error error - * @return return value of native call - */ - static native String elf_errmsg(int error); - - /** - * Invoke native libelf function size_t elf_ndxscn (Elf_Scn *scn). - * - * @param scn section pointer - * @return return value of native call - */ - static native int elf_ndxscn(Pointer scn); - - /** - * GELF interfaces - */ - /** - * Invoke native libelf function unsigned long int gelf_newehdr (Elf *elf, int elfClass). - * - * @param elf ELF Header pointer - * @param elfclass ELF class - * @return return value of native call boxed as a pointer - */ - static native Pointer gelf_newehdr(Pointer elf, int elfclass); - - /** - * Invoke native libelf function unsigned long int gelf_newphdr (Elf *elf, size_t phnum). - * - * @param elf ELF header pointer - * @param phnum number of program headers - * @return return value of native call boxed as a pointer - */ - static native Pointer gelf_newphdr(Pointer elf, int phnum); - - /** - * Miscellaneous convenience native methods that help peek and poke ELF data structures. - */ - static native int size_of_Sym(int elfClass); - - static native int size_of_Rela(int elfClass); - - static native int size_of_Rel(int elfClass); - - static native void ehdr_set_data_encoding(Pointer ehdr, int val); - - static native void set_Ehdr_e_machine(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_type(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_version(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_shstrndx(int elfclass, Pointer structPtr, int val); - - static native void phdr_set_type_self(int elfclass, Pointer ehdr, Pointer phdr); - - static native void set_Shdr_sh_name(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_type(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_flags(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_entsize(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_link(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_info(int elfclass, Pointer structPtr, int val); - - static native void set_Data_d_align(Pointer structPtr, int val); - - static native void set_Data_d_off(Pointer structPtr, int val); - - static native void set_Data_d_buf(Pointer structPtr, Pointer val); - - static native void set_Data_d_type(Pointer structPtr, int val); - - static native void set_Data_d_size(Pointer structPtr, int val); - - static native void set_Data_d_version(Pointer structPtr, int val); - - static native long create_sym_entry(int elfclass, int index, int type, int bind, int shndx, int size, int value); - - static native long create_reloc_entry(int elfclass, int roffset, int symtabIdx, int relocType, int raddend, int reloca); - - /** - * File Operations. - */ - static native int open_rw(String fileName); - - static native int open(String fileName, int flags); - - static native int open(String fileName, int flags, int mode); - - static native int close(int fd); - // Checkstyle: resume method name check -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java deleted file mode 100644 index a569584a8ce..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java +++ /dev/null @@ -1,72 +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 jdk.tools.jaotc.jnilibelf; - -import jdk.internal.misc.Unsafe; - -import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE; - -public class Pointer { - - private final long address; - - public Pointer(long val) { - address = val; - } - - /** - * Put (i.e., copy) content of byte array at consecutive addresses beginning at this Pointer. - * - * @param src source byte array - */ - public void put(byte[] src) { - UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length); - } - - /** - * Get (i.e., copy) content at this Pointer to the given byte array. - * - * @param dst destination byte array - */ - public void get(byte[] dst) { - UNSAFE.copyMemory(null, address, dst, Unsafe.ARRAY_BYTE_BASE_OFFSET, dst.length); - } - - /** - * Read {@code readSize} number of bytes to copy them starting at {@code startIndex} of - * {@code byteArray} - * - * @param byteArray target array to copy bytes - * @param readSize number of bytes to copy - * @param startIndex index of the array to start copy at - */ - public void copyBytesTo(byte[] byteArray, int readSize, int startIndex) { - long end = (long)startIndex + (long)readSize; - if (end > byteArray.length) { - throw new IllegalArgumentException("writing beyond array bounds"); - } - UNSAFE.copyMemory(null, address, byteArray, Unsafe.ARRAY_BYTE_BASE_OFFSET+startIndex, readSize); - } - -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java deleted file mode 100644 index a32d202486c..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java +++ /dev/null @@ -1,80 +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 jdk.tools.jaotc.jnilibelf.linux; - -/** - * Represent Elf_Cmd enums defined in libelf.h on Linux as they slightly different from libelf.h on - * SunOS. - */ -public enum Elf_Cmd { - /** Nothing, terminate, or compute only. */ - ELF_C_NULL, - - /** Read. */ - ELF_C_READ, - - /** Read and write. */ - ELF_C_RDWR, - - /** Write. */ - ELF_C_WRITE, - - /** Clear flag. */ - ELF_C_CLR, - - /** Set flag. */ - ELF_C_SET, - - /** - * Signal that file descriptor will not be used anymore. - */ - ELF_C_FDDONE, - - /** - * Read rest of data so that file descriptor is not used anymore. - */ - ELF_C_FDREAD, - - /* The following are extensions. */ - - /** Read, but mmap the file if possible. */ - ELF_C_READ_MMAP, - - /** Read and write, with mmap. */ - ELF_C_RDWR_MMAP, - - /** Write, with mmap. */ - ELF_C_WRITE_MMAP, - - /** - * Read, but memory is writable, results are not written to the file. - */ - ELF_C_READ_MMAP_PRIVATE, - - /** Copy basic file data but not the content. */ - ELF_C_EMPTY, - - /** Keep this the last entry. */ - ELF_C_NUM; -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java index 3ba1067b959..7d3bf7c258f 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java @@ -23,17 +23,12 @@ package jdk.tools.jaotc; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import java.util.ListIterator; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompiler; -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -43,8 +38,7 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; @@ -60,19 +54,18 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.TriState; public class AOTBackend { - private final Main main; - + private final OptionValues graalOptions; private final HotSpotBackend backend; - private final HotSpotProviders providers; private final HotSpotCodeCacheProvider codeCache; private final PhaseSuite graphBuilderSuite; private final HighTierContext highTierContext; private final GraalFilters filters; - public AOTBackend(Main main, HotSpotBackend backend, GraalFilters filters) { + public AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, GraalFilters filters) { this.main = main; + this.graalOptions = graalOptions; this.backend = backend; this.filters = filters; providers = backend.getProviders(); @@ -85,25 +78,27 @@ public class AOTBackend { return graphBuilderSuite; } + public HotSpotBackend getBackend() { + return backend; + } + private Suites getSuites() { // create suites every time, as we modify options for the compiler - return backend.getSuites().getDefaultSuites(); + return backend.getSuites().getDefaultSuites(graalOptions); } private LIRSuites getLirSuites() { // create suites every time, as we modify options for the compiler - return backend.getSuites().getDefaultLIRSuites(); + return backend.getSuites().getDefaultLIRSuites(graalOptions); } @SuppressWarnings("try") public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod) { - try (OverrideScope s = OptionValue.override(ImmutableCode, true, GeneratePIC, true)) { - StructuredGraph graph = buildStructuredGraph(resolvedMethod); - if (graph != null) { - return compileGraph(resolvedMethod, graph); - } - return null; + StructuredGraph graph = buildStructuredGraph(resolvedMethod); + if (graph != null) { + return compileGraph(resolvedMethod, graph); } + return null; } /** @@ -115,7 +110,7 @@ public class AOTBackend { @SuppressWarnings("try") private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod) { try (Scope s = Debug.scope("AOTParseMethod")) { - StructuredGraph graph = new StructuredGraph(javaMethod, StructuredGraph.AllowAssumptions.NO, false, CompilationIdentifier.INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(graalOptions).method(javaMethod).useProfilingInfo(false).build(); graphBuilderSuite.apply(graph, highTierContext); return graph; } catch (Throwable e) { @@ -195,7 +190,7 @@ public class AOTBackend { public void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) { // This is really not installing the method. - InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult), null, null); + InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult), null, null); String disassembly = codeCache.disassemble(installedCode); if (disassembly != null) { main.printlnDebug(disassembly); diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java index f92ead4ba25..8cd0b5f6bb1 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -54,6 +55,8 @@ public class AOTCompilationTask implements Runnable, Comparable { private final Main main; + private OptionValues graalOptions; + /** * The compilation id of this task. */ @@ -73,9 +76,10 @@ public class AOTCompilationTask implements Runnable, Comparable { */ private CompiledMethodInfo result; - public AOTCompilationTask(Main main, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { + public AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { this.main = main; - this.id = ids.getAndIncrement(); + this.graalOptions = graalOptions; + this.id = ids.incrementAndGet(); this.holder = holder; this.method = method; this.aotBackend = aotBackend; @@ -91,14 +95,14 @@ public class AOTCompilationTask implements Runnable, Comparable { // Ensure a debug configuration for this thread is initialized if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(TTY.out); + DebugEnvironment.ensureInitialized(graalOptions); } AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling"); final long threadId = Thread.currentThread().getId(); - final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue() && !TTY.isSuppressed(); - final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue() && !TTY.isSuppressed(); + final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed(); + final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue(graalOptions) && !TTY.isSuppressed(); if (printCompilation) { TTY.println(getMethodDescription() + "..."); } @@ -123,11 +127,7 @@ public class AOTCompilationTask implements Runnable, Comparable { final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId); final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; - if (printAfterCompilation) { - TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes)); - } else if (printCompilation) { - TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dkB", getId(), "", "", "", stop - start, targetCodeSize, allocatedBytes)); - } + TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes)); } if (compResult == null) { @@ -141,11 +141,11 @@ public class AOTCompilationTask implements Runnable, Comparable { aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult); } - result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method)); + result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend())); } private String getMethodDescription() { - return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(), + return String.format("%-6d aot %s %s", getId(), MiscUtils.uniqueMethodName(method), getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java index 12a72c42dfa..7b708cb1d9c 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java @@ -31,12 +31,16 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.compiler.options.OptionValues; + import jdk.vm.ci.meta.ResolvedJavaMethod; public class AOTCompiler { private final Main main; + private final OptionValues graalOptions; + private CompileQueue compileQueue; private final AOTBackend backend; @@ -102,11 +106,13 @@ public class AOTCompiler { /** * @param main + * @param graalOptions * @param aotBackend * @param threads number of compilation threads */ - public AOTCompiler(Main main, AOTBackend aotBackend, final int threads) { + public AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) { this.main = main; + this.graalOptions = graalOptions; this.compileQueue = new CompileQueue(threads); this.backend = aotBackend; } @@ -146,7 +152,7 @@ public class AOTCompiler { * @param method method to be enqueued */ private void enqueueMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method) { - AOTCompilationTask task = new AOTCompilationTask(main, aotClass, method, backend); + AOTCompilationTask task = new AOTCompilationTask(main, graalOptions, aotClass, method, backend); try { compileQueue.execute(task); } catch (RejectedExecutionException e) { diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java index 865ef46c89a..bff6a5124e1 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java @@ -24,6 +24,7 @@ package jdk.tools.jaotc; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -31,9 +32,11 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo { private final HotSpotResolvedJavaMethod method; + private final Backend backend; - public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method) { + public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) { this.method = method; + this.backend = backend; } public String getSymbolName() { @@ -46,7 +49,7 @@ public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo { } public HotSpotCompiledCode compiledCode(CompilationResult result) { - return HotSpotCompiledCodeBuilder.createCompiledCode(method, null, result); + return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result); } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java index 1eabbdc3a78..b1cd89975ba 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java @@ -49,7 +49,7 @@ public class AOTStub implements JavaMethodInfo { } public HotSpotCompiledCode compiledCode(CompilationResult result) { - return HotSpotCompiledCodeBuilder.createCompiledCode(null, null, result); + return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result); } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java index 159955c6bda..097670b7974 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.hotspot.HotSpotHostBackend; +import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -180,7 +181,8 @@ class DataBuilder { @SuppressWarnings("try") private AOTCompiledClass retrieveStubCode() { ArrayList stubs = new ArrayList<>(); - for (Stub stub : Stub.getStubs()) { + HotSpotForeignCallsProvider foreignCallsProvider = backend.getProviders().getForeignCalls(); + for (Stub stub : foreignCallsProvider.getStubs()) { try (Scope scope = Debug.scope("CompileStubs")) { CompilationResult result = stub.getCompilationResult(backend); CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend)); diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java index d9cb0b27aef..988ebf9c0a4 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java @@ -43,7 +43,7 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions; import org.graalvm.compiler.hotspot.word.MetaspacePointer; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.word.WordBase; +import org.graalvm.word.WordBase; public class GraalFilters { private List specialClasses; diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java index 933e91acaf4..d00d6bbb3e1 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java @@ -60,11 +60,15 @@ import jdk.tools.jaotc.collect.module.ModuleSourceProvider; import jdk.tools.jaotc.utils.Timer; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.hotspot.CompilerConfigurationFactory; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory; +import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -76,11 +80,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.runtime.JVMCI; public class Main implements LogPrinter { - static { - GeneratePIC.setValue(true); - ImmutableCode.setValue(true); - } - static class BadArgs extends Exception { private static final long serialVersionUID = 1L; final String key; @@ -132,13 +131,10 @@ public class Main implements LogPrinter { abstract void process(Main task, String opt, String arg) throws BadArgs; } - static Option[] recognizedOptions = { new Option(" --output Output file name", true, "--output") { + static Option[] recognizedOptions = {new Option(" --output Output file name", true, "--output") { @Override void process(Main task, String opt, String arg) { String name = arg; - if (name.endsWith(".so")) { - name = name.substring(0, name.length() - ".so".length()); - } task.options.outputName = name; } }, new Option(" --class-name List of classes to compile", true, "--class-name", "--classname") { @@ -175,7 +171,7 @@ public class Main implements LogPrinter { }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") { @Override void process(Main task, String opt, String arg) { - TieredAOT.setValue(true); + task.options.tiered = true; } }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") { @Override @@ -234,6 +230,11 @@ public class Main implements LogPrinter { void process(Main task, String opt, String arg) { task.options.version = true; } + }, new Option(" --linker-path Full path to linker executable", true, "--linker-path") { + @Override + void process(Main task, String opt, String arg) { + task.options.linkerpath = arg; + } }, new Option(" -J Pass directly to the runtime system", false, "-J") { @Override void process(Main task, String opt, String arg) { @@ -242,9 +243,10 @@ public class Main implements LogPrinter { public static class Options { public List files = new LinkedList<>(); - public String outputName = "unnamed"; + public String outputName = "unnamed.so"; public String methodList; public List sources = new ArrayList<>(); + public String linkerpath = null; public SearchPath searchPath = new SearchPath(); /** @@ -262,6 +264,7 @@ public class Main implements LogPrinter { public boolean help; public boolean version; public boolean compileWithAssertions; + public boolean tiered; } /* package */final Options options = new Options(); @@ -304,7 +307,7 @@ public class Main implements LogPrinter { printlnInfo("Compiling " + options.outputName + "..."); final long start = System.currentTimeMillis(); if (!run()) { - return EXIT_ABNORMAL; + return EXIT_ABNORMAL; } final long end = System.currentTimeMillis(); printlnInfo("Total time: " + (end - start) + " ms"); @@ -347,6 +350,64 @@ public class Main implements LogPrinter { } } + /** + * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012 + */ + public enum VSVERSIONS { + VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"), + VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"), + VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe"); + + private final String envvariable; + private final String wkp; + + VSVERSIONS(String envvariable, String wellknownpath) { + this.envvariable = envvariable; + this.wkp = wellknownpath; + } + + String EnvVariable() { + return envvariable; + } + + String WellKnownPath() { + return wkp; + } + } + + /** + * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012 + */ + private static String getWindowsLinkPath() { + String link = "\\VC\\bin\\amd64\\link.exe"; + + /** + * First try searching the paths pointed to by the VS environment variables. + */ + for (VSVERSIONS vs : VSVERSIONS.values()) { + String vspath = System.getenv(vs.EnvVariable()); + if (vspath != null) { + File commonTools = new File(vspath); + File vsRoot = commonTools.getParentFile().getParentFile(); + File linkPath = new File(vsRoot, link); + if (linkPath.exists()) + return linkPath.getPath(); + } + } + + /** + * If we didn't find via the VS environment variables, try the well known paths + */ + for (VSVERSIONS vs : VSVERSIONS.values()) { + String wkp = vs.WellKnownPath(); + if (new File(wkp).exists()) { + return wkp; + } + } + + return null; + } + @SuppressWarnings("try") private boolean run() throws Exception { openLog(); @@ -379,7 +440,13 @@ public class Main implements LogPrinter { printInfo(classesToCompile.size() + " classes found"); } - GraalJVMCICompiler graalCompiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler(); + OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + // Setting -Dgraal.TieredAOT overrides --compile-for-tiered + if (!TieredAOT.hasBeenSet(graalOptions)) { + graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered); + } + graalOptions = new OptionValues(HotSpotGraalOptionValues.HOTSPOT_OPTIONS, GeneratePIC, true, ImmutableCode, true); + GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(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(); @@ -399,8 +466,8 @@ public class Main implements LogPrinter { System.gc(); } - AOTBackend aotBackend = new AOTBackend(this, backend, filters); - AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads); + AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, filters); + AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads); classes = compiler.compileClasses(classes); GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig(); @@ -416,7 +483,7 @@ public class Main implements LogPrinter { System.gc(); } - BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); + BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer); dataBuilder.prepareData(); @@ -451,8 +518,58 @@ public class Main implements LogPrinter { System.gc(); } - String objectFileName = options.outputName + ".o"; - String libraryFileName = options.outputName + ".so"; + String name = options.outputName; + String objectFileName = name; + + // [TODO] The jtregs tests expect .so extension so don't + // override with platform specific file extension until the + // tests are fixed. + String libraryFileName = name; + + String linkerCmd; + String linkerPath; + String osName = System.getProperty("os.name"); + + if (name.endsWith(".so")) { + objectFileName = name.substring(0, name.length() - ".so".length()); + } else if (name.endsWith(".dylib")) { + objectFileName = name.substring(0, name.length() - ".dylib".length()); + } else if (name.endsWith(".dll")) { + objectFileName = name.substring(0, name.length() - ".dll".length()); + } + + switch (osName) { + case "Linux": + // libraryFileName = options.outputName + ".so"; + objectFileName = objectFileName + ".o"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName; + break; + case "SunOS": + // libraryFileName = options.outputName + ".so"; + objectFileName = objectFileName + ".o"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName; + break; + case "Mac OS X": + // libraryFileName = options.outputName + ".dylib"; + objectFileName = objectFileName + ".o"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName; + break; + default: + if (osName.startsWith("Windows")) { + // libraryFileName = options.outputName + ".dll"; + objectFileName = objectFileName + ".obj"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath(); + if (linkerPath == null) { + throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe"); + } + linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName; + break; + } else + throw new InternalError("Unsupported platform: " + osName); + } try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) { binaryContainer.createBinary(objectFileName, JVM_VERSION); @@ -466,7 +583,7 @@ public class Main implements LogPrinter { } try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) { - Process p = Runtime.getRuntime().exec("ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName); + Process p = Runtime.getRuntime().exec(linkerCmd); final int exitCode = p.waitFor(); if (exitCode != 0) { InputStream stderr = p.getErrorStream(); @@ -484,7 +601,7 @@ public class Main implements LogPrinter { } // Make non-executable for all. File libFile = new File(libraryFileName); - if (libFile.exists()) { + if (libFile.exists() && !osName.startsWith("Windows")) { if (!libFile.setExecutable(false, false)) { throw new InternalError("Failed to change attribute for " + libraryFileName + " file"); } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java index 8d9b8439760..7840be5bf2d 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java @@ -31,6 +31,20 @@ public interface ClassSource { return fileName.endsWith(".class") && !fileName.endsWith("module-info.class"); } + static String stripRoot(Path path) { + if (path.getRoot() != null) { + String root = path.getRoot().toString(); + String filename = path.toString().substring(root.length()); + String separator = path.getFileSystem().getSeparator(); + while (filename.startsWith(separator)) { + filename = filename.substring(separator.length()); + } + return filename; + } + + return path.toString(); + } + static String makeClassName(Path path) { String fileName = path.toString(); @@ -38,13 +52,10 @@ public interface ClassSource { throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'"); } - int start = 0; - if (fileName.startsWith("/")) { - start = 1; - } + fileName = stripRoot(path); - String className = fileName.substring(start, fileName.length() - ".class".length()); - className = className.replace('/', '.'); + String className = fileName.substring(0, fileName.length() - ".class".length()); + className = className.replace(path.getFileSystem().getSeparator(), "."); return className; } diff --git a/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c b/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c deleted file mode 100644 index b64bc2dfdbc..00000000000 --- a/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c +++ /dev/null @@ -1,526 +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. - */ - -#include "jdk_tools_jaotc_jnilibelf_JNILibELFAPI.h" - -// For file open and close -#include -#include -#include -#include -#include -#include - -#include - -// For libelf interfaces -#include -#include - -// Convenience macro to shut the compiler warnings -#ifdef UNUSED -#elif defined(__GNUC__) -# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) -#elif defined(__LCLINT__) -# define UNUSED(x) /*@unused@*/ x -#else -# define UNUSED(x) x -#endif - -/** - * libelfshim version - */ -#ifndef AOT_VERSION_STRING - #error AOT_VERSION_STRING must be defined -#endif - -JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elfshim_1version -(JNIEnv* env, jclass UNUSED(c)) { - const char* ver = AOT_VERSION_STRING; - return (*env)->NewStringUTF(env, ver); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1version -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint v) { - return elf_version(v); -} - -/** - * Unbox the Pointer object the encapsulated native address. - */ - -static jlong getNativeAddress(JNIEnv* env, jobject ptrObj) { - jlong nativeAddress = -1; - assert (ptrObj != NULL); - // Get a reference to ptr object's class - jclass ptrClass = (*env)->GetObjectClass(env, ptrObj); - if (ptrClass != NULL) { - // Get the Field ID of the instance variables "address" - jfieldID fidNumber = (*env)->GetFieldID(env, ptrClass, "address", "J"); - if (fidNumber != NULL) { - // Get the long given the Field ID - nativeAddress = (*env)->GetLongField(env, ptrObj, fidNumber); - } - } - // fprintf(stderr, "Native address : %lx\n", nativeAddress); - return nativeAddress; -} - -/** - * Box the nativeAddress as a Pointer object. - */ -static jobject makePointerObject(JNIEnv* env, jlong nativeAddr) { - jobject retObj = NULL; - jclass ptrClass = (*env)->FindClass(env, "jdk/tools/jaotc/jnilibelf/Pointer"); - if (ptrClass != NULL) { - // Call back constructor to allocate a Pointer object, with an int argument - jmethodID constructorId = (*env)->GetMethodID(env, ptrClass, "", "(J)V"); - if (constructorId != NULL) { - retObj = (*env)->NewObject(env, ptrClass, constructorId, nativeAddr); - } - } - return retObj; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1begin -(JNIEnv* env, jclass UNUSED(class), jint filedes, jint cmd, jobject ptrObj) { - - Elf* elfPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfPtr = elf_begin(filedes, cmd, (Elf *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_begin()\n"); - } - - return makePointerObject(env, (jlong) elfPtr); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1end -(JNIEnv* env, jclass UNUSED(class), jobject ptrObj) { - - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - return elf_end((Elf *) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_end()\n"); - return -1; - } -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1kind -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - return elf_kind((Elf *) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_kind()\n"); - return -1; - } -} -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1flagphdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd, jint flags) { - - jlong addr = getNativeAddress(env, ptrObj); - unsigned int retVal = 0; - - if (addr != -1) { - // Call libelf function - if ((retVal = elf_flagphdr((Elf *) addr, cmd, flags)) == 0) { - errx(EX_SOFTWARE, "elf_flagphdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_flagphdr()\n"); - } - return retVal; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newscn -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf_Scn* elfSecPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfSecPtr = elf_newscn((Elf *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_newscn() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newscn()\n"); - } - - return makePointerObject(env, (jlong) elfSecPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newdata -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf_Data* elfDataPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfDataPtr = elf_newdata((Elf_Scn *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newdata()\n"); - } - return makePointerObject(env, (jlong) elfDataPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf64_1getshdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf64_Shdr* elf64ShdrPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elf64ShdrPtr = elf64_getshdr((Elf_Scn *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf64_getshdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_getshdr()\n"); - } - return makePointerObject(env, (jlong) elf64ShdrPtr); -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1update -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd) { - - off_t size = -1; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((size = elf_update((Elf*) addr, cmd)) == -1) { - errx(EX_SOFTWARE, "elf_update() failed: %s size (%d) cmd (%d).", elf_errmsg(-1), (int)size, cmd); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_update()\n"); - } - return size; -} - -JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1errmsg -(JNIEnv* env, jclass UNUSED(c), jint errno) { - - const char * retPtr = NULL; - // Call libelf function - if ((retPtr = elf_errmsg(errno)) == NULL) { - errx(EX_SOFTWARE, "elf_errmsg() failed: %s.", elf_errmsg(-1)); - } - return (*env)->NewStringUTF(env, retPtr); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1ndxscn -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - jint secnum = SHN_UNDEF; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - secnum = elf_ndxscn((Elf_Scn*) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_ndxscn()\n"); - } - return secnum; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newehdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint elfClass) { - unsigned long int retPtr = 0; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - if ((retPtr = gelf_newehdr((Elf*) addr, elfClass)) == 0) { - errx(EX_SOFTWARE, "gelf_newehdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newehdr()\n"); - } - return makePointerObject(env, (jlong) retPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newphdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint phnum) { - unsigned long int retPtr = 0; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - if ((retPtr = gelf_newphdr((Elf*) addr, phnum)) == 0) { - errx(EX_SOFTWARE, "gelf_newphdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newphdr()\n"); - } - return makePointerObject(env, (jlong) retPtr); -} - - -/* File operations */ - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open_1rw -(JNIEnv * env, jclass UNUSED(class), jstring jfileName) { - int flags = O_RDWR | O_CREAT | O_TRUNC; - int mode = 0666; - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags, mode); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2I -(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags) { - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2II -(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags, jint mode) { - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags, mode); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_close -(JNIEnv* UNUSED(env), jclass UNUSED(class), jint fd) { - return close(fd); -} - -/** - * Miscellaneous ELF data structure peek-poke functions in - * shim_functions.c. No corresponding .h file exists yet. - * So each function needs to be declared as extern - */ - -extern int size_of_Sym(int elfclass); -extern int size_of_Rel(int elfclass); -extern int size_of_Rela(int elfclass); - -extern void ehdr_set_data_encoding(void * ehdr, int val); -extern void set_Ehdr_e_machine(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_type(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_version(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_shstrndx(int elfclass, void * structPtr, int val); - -extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr); -extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr); - -extern void set_Shdr_sh_name(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_type(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_flags(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_entsize(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_link(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_info(int elfclass, void* structPtr, int val); - -extern void set_Data_d_align(void* structPtr, int val); -extern void set_Data_d_off(void* structPtr, int val); -extern void set_Data_d_buf(void* structPtr, void* val); -extern void set_Data_d_type(void* structPtr, int val); -extern void set_Data_d_size(void* structPtr, int val); -extern void set_Data_d_version(void* structPtr, int val); - -extern void* create_sym_entry(int elfclass, int index, int type, int bind, - int shndx, int size, int value); -extern void * create_reloc_entry(int elfclass, int roffset, int symtabIdx, - int relocType, int raddend, int reloca); - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Sym -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Sym(elfClass); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rela -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Rela(elfClass); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rel -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Rel(elfClass); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_ehdr_1set_1data_1encoding -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - ehdr_set_data_encoding(ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1machine -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_machine(elfClass, ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1type -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_type(elfClass, ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1version -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_version(elfClass, ehdr, val); -} -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1shstrndx -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_shstrndx(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_phdr_1set_1type_1self -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ehdrPtr, jobject phdrPtr) { - void* ehdr = (void*) getNativeAddress(env, ehdrPtr); - void* phdr = (void*) getNativeAddress(env, phdrPtr); - phdr_set_type_self(elfClass, ehdr, phdr); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1name -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_name(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1type -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_type(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1flags -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_flags(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1entsize -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_entsize(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1info -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_info(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1link -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_link(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1align -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_align(dptr, val); -} - - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1off -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_off(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1buf -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jobject bufPtr) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - void* bptr = (void*) getNativeAddress(env, bufPtr); - set_Data_d_buf(dptr, bptr); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1type -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_type(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1size -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_size(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1version -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_version(dptr, val); -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1sym_1entry -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint index, jint type, - jint bind, jint shndx, jint size, jint value) { - void * retVal = create_sym_entry(elfClass, index, type, bind, - shndx, size, value); - return (jlong)retVal; -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1reloc_1entry -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint roffset, - jint symTabIdx, jint relocType, jint raddend, jint reloca) { - void * retVal = create_reloc_entry(elfClass, roffset, symTabIdx, - relocType, raddend, reloca); - return (jlong)retVal; -} - diff --git a/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c b/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c deleted file mode 100644 index e405b0d26c0..00000000000 --- a/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c +++ /dev/null @@ -1,226 +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. - */ - -#include -#include -#include - -/** - * TODO: This is an intial and crude attempt to access structure - * fields of some ELF structrures. Need to figure out a way to access the - * given field of a given structure instead of writing one shim function - * per access of each of the structure field. - **/ - -#define STRINGIFYHELPER(x) #x -#define STRINGIFY(x) STRINGIFYHELPER(x) -#define FUNC_NAME(S, F) set_ ## S ## _ ## F -#define CAST_STRUCT(S, F) ((Elf_ ## S *) structPtr) -#define CAST_STRUCT32(S, F) ((Elf32_ ## S *) structPtr) -#define CAST_STRUCT64(S, F) ((Elf64_ ## S *) structPtr) -#define ACCESS_FIELD(S, F) CAST_STRUCT(S, F)-> F -#define ACCESS_FIELD32(S, F) CAST_STRUCT32(S, F)-> F -#define ACCESS_FIELD64(S, F) CAST_STRUCT64(S, F)-> F - -/* - Example: - SET_TYPE_BASED_FIELD(Ehdr, e_machine, int) - expands to - set_Ehdr_e_machine(int elfclass, void * strPtr, int val) { -} -*/ - -#define SET_TYPE_BASED_FIELD(S, F, T) \ - void FUNC_NAME(S, F)(int elfclass, void * structPtr, T val) { \ - if (elfclass == ELFCLASS32) { \ - ACCESS_FIELD32(S, F) = val; \ - } else if (elfclass == ELFCLASS64) { \ - ACCESS_FIELD64(S, F) = val; \ - } else { \ - printf("%s: Unknown ELF Class %d provided\n", STRINGIFY(FUNC_NAME(S, F)), elfclass); \ - } \ - return; \ -} - -/* - Example: - SET_FIELD(Ehdr, e_machine, int) - expands to - set_Ehdr_e_machine(void * strPtr, int val) { -} -*/ - -#define SET_FIELD(S, F, T) \ - void FUNC_NAME(S, F)(void * structPtr, T val) { \ - ACCESS_FIELD(S, F) = val; \ - return; \ -} - -int size_of_Sym(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Sym); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Sym); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -int size_of_Rela(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Rela); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Rela); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -int size_of_Rel(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Rel); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Rel); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -/* ELF Header field access */ - -void ehdr_set_data_encoding(void * ehdr, int val) { - ((Elf32_Ehdr *) ehdr)->e_ident[EI_DATA] = val; - return; -} - -SET_TYPE_BASED_FIELD(Ehdr, e_machine, int) -SET_TYPE_BASED_FIELD(Ehdr, e_type, int) -SET_TYPE_BASED_FIELD(Ehdr, e_version, int) -SET_TYPE_BASED_FIELD(Ehdr, e_shstrndx, int) - -/* Data descriptor field access */ -SET_FIELD(Data, d_align, int) -SET_FIELD(Data, d_off, int) -SET_FIELD(Data, d_buf, void*) -SET_FIELD(Data, d_type, int) -SET_FIELD(Data, d_size, int) -SET_FIELD(Data, d_version, int) - -/* Section Header Access functions */ -SET_TYPE_BASED_FIELD(Shdr, sh_name, int) -SET_TYPE_BASED_FIELD(Shdr, sh_type, int) -SET_TYPE_BASED_FIELD(Shdr, sh_flags, int) -SET_TYPE_BASED_FIELD(Shdr, sh_entsize, int) -SET_TYPE_BASED_FIELD(Shdr, sh_link, int) -SET_TYPE_BASED_FIELD(Shdr, sh_info, int) - -/* Set the Program Header to be of PH_PHDR type and initialize other - related fields of the program header. -*/ -void phdr_set_type_self(int elfclass, void * ehdr, void * phdr) { - if (elfclass == ELFCLASS32) { - Elf32_Ehdr * ehdr32 = (Elf32_Ehdr *) ehdr; - Elf32_Phdr * phdr32 = (Elf32_Phdr *) phdr; - phdr32->p_type = PT_PHDR; - phdr32->p_offset = ehdr32->e_phoff; - phdr32->p_filesz = elf32_fsize(ELF_T_PHDR, 1, EV_CURRENT); - } else if (elfclass == ELFCLASS64) { - Elf64_Ehdr * ehdr64 = (Elf64_Ehdr *) ehdr; - Elf64_Phdr * phdr64 = (Elf64_Phdr *) phdr; - phdr64->p_type = PT_PHDR; - phdr64->p_offset = ehdr64->e_phoff; - phdr64->p_filesz = elf64_fsize(ELF_T_PHDR, 1, EV_CURRENT); - } else { - printf("phdr_set_type_self: Unknown ELF Class %d provided\n", elfclass); - } - return; -} - -/* - Create symbol table entry with given type and binding -*/ -void * create_sym_entry(int elfclass, int index, int type, int bind, - int shndx, int size, int value) { - void * symentry = NULL; - if (elfclass == ELFCLASS32) { - Elf32_Sym * sym32 = (Elf32_Sym *) malloc(sizeof(Elf32_Sym)); - sym32->st_name = index; - sym32->st_value = value; - sym32->st_size = size; - sym32->st_info = ELF32_ST_INFO(bind, type); - sym32->st_other = 0; // TODO: Add an argument to get this value ?? - sym32->st_shndx = shndx; - symentry = sym32; - } else if (elfclass == ELFCLASS64) { - Elf64_Sym * sym64 = (Elf64_Sym *) malloc(sizeof(Elf64_Sym)); - sym64->st_name = index; - sym64->st_value = value; - sym64->st_size = size; - sym64->st_info = ELF64_ST_INFO(bind, type); - sym64->st_other = 0; // TODO: Add an argument to get this value ?? - sym64->st_shndx = shndx; - symentry = sym64; - } else { - printf("create_sym_entry: Unknown ELF Class %d provided\n", elfclass); - } - return (void *) symentry; -} - -// Create a reloc (or reloca entry if argument reloca is non-zero) -void * create_reloc_entry(int elfclass, int roffset, int symtabIdx, - int relocType, int raddend, int reloca) { - void * relocentry = NULL; - if (elfclass == ELFCLASS32) { - if (reloca) { - Elf32_Rela * rela32 = (Elf32_Rela *) malloc(sizeof(Elf32_Rela)); - rela32->r_offset = roffset; - rela32->r_info = ELF32_R_INFO(symtabIdx, relocType); - rela32->r_addend = raddend; - relocentry = rela32; - } else { - Elf32_Rel * rel32 = (Elf32_Rel *) malloc(sizeof(Elf32_Rel)); - rel32->r_offset = roffset; - rel32->r_info = ELF32_R_INFO(symtabIdx, relocType); - relocentry = rel32; - } - } else if (elfclass == ELFCLASS64) { - if (reloca) { - Elf64_Rela * rela64 = (Elf64_Rela *) malloc(sizeof(Elf64_Rela)); - rela64->r_offset = roffset; - rela64->r_info = ELF64_R_INFO(symtabIdx, relocType); - rela64->r_addend = raddend; - relocentry = rela64; - } else { - Elf64_Rel * rel64 = (Elf64_Rel *) malloc(sizeof(Elf64_Rel)); - rel64->r_offset = roffset; - rel64->r_info = ELF64_R_INFO(symtabIdx, relocType); - relocentry = rel64; - } - } else { - printf("create_reloc_entry: Unknown ELF Class %d provided\n", elfclass); - } - return (void *) relocentry; -} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java index 14c8ee8118d..aaa00e9a5a0 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java @@ -39,8 +39,6 @@ public interface MachineTypes { public static final short IMAGE_FILE_MACHINE_ALPHA64 = (short) 0x284; /** Intel 386 or later, and compatible processors. */ public static final short IMAGE_FILE_MACHINE_I386 = (short) 0x14c; - /** Intel IA64 */ - public static final short IMAGE_FILE_MACHINE_IA64 = (short) 0x200; /** Motorola 68000 series. */ public static final short IMAGE_FILE_MACHINE_M68K = (short) 0x268; public static final short IMAGE_FILE_MACHINE_MIPS16 = (short) 0x266; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java index d9da1570b89..9a714b9c8a9 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -121,14 +121,7 @@ public class BytecodeLoadConstant extends Bytecode { // decide based on the oop type. ConstantPool cpool = method().getConstants(); int cpIndex = poolIndex(); - ConstantPool.CPSlot oop = cpool.getSlotAt(cpIndex); - if (oop.isResolved()) { - return oop.getKlass(); - } else if (oop.isUnresolved()) { - return oop.getSymbol(); - } else { - throw new RuntimeException("should not reach here"); - } + return cpool.getKlassNameAt(cpIndex); } public static BytecodeLoadConstant at(Method method, int bci) { @@ -171,12 +164,12 @@ public class BytecodeLoadConstant extends Bytecode { // tag change from 'unresolved' to 'klass' does not happen atomically. // We just look at the object at the corresponding index and // decide based on the oop type. - ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); - if (obj.isResolved()) { - Klass k = obj.getKlass(); + ConstantTag tag = cpool.getTagAt(cpIndex); + if (tag.isKlass()) { + Klass k = cpool.getKlassAt(cpIndex); return ""; - } else if (obj.isUnresolved()) { - Symbol sym = obj.getSymbol(); + } else if (tag.isUnresolvedKlass()) { + Symbol sym = cpool.getKlassNameAt(cpIndex); return ""; } else { throw new RuntimeException("should not reach here"); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java index 7e06cce1779..8ad0aa7e9b3 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -37,12 +37,7 @@ public class BytecodeWithKlass extends BytecodeWithCPIndex { } public Symbol getClassName() { - ConstantPool.CPSlot obj = method().getConstants().getSlotAt(index()); - if (obj.isUnresolved()) { - return obj.getSymbol(); - } else { - return obj.getKlass().getName(); - } + return method().getConstants().getKlassNameAt(index()); } public String toString() { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java index fc1f461acd4..c7285ed316d 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -35,30 +35,35 @@ import sun.jvm.hotspot.utilities.*; // as described in the class file public class ConstantPool extends Metadata implements ClassConstants { - public class CPSlot { + private class CPSlot { private Address ptr; CPSlot(Address ptr) { this.ptr = ptr; } - CPSlot(Symbol sym) { - this.ptr = sym.getAddress().orWithMask(1); - } - - public boolean isResolved() { - return (ptr.minus(null) & 1) == 0; - } - public boolean isUnresolved() { - return (ptr.minus(null) & 1) == 1; - } public Symbol getSymbol() { - if (!isUnresolved()) throw new InternalError("not a symbol"); - return Symbol.create(ptr.xorWithMask(1)); + // (Lowest bit == 1) -> this is an pseudo string. + return Symbol.create(ptr.andWithMask(~1)); + } + } + private class CPKlassSlot { + private int name_index; + private int resolved_klass_index; + private static final int temp_resolved_klass_index = 0xffff; + + public CPKlassSlot(int n, int rk) { + name_index = n; + resolved_klass_index = rk; + } + public int getNameIndex() { + return name_index; + } + public int getResolvedKlassIndex() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(resolved_klass_index != temp_resolved_klass_index, "constant pool merging was incomplete"); } - public Klass getKlass() { - if (!isResolved()) throw new InternalError("not klass"); - return (Klass)Metadata.instantiateWrapperFor(ptr); + return resolved_klass_index; } } @@ -84,8 +89,7 @@ public class ConstantPool extends Metadata implements ClassConstants { cache = type.getAddressField("_cache"); poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0); length = new CIntField(type.getCIntegerField("_length"), 0); - resolvedReferences = type.getAddressField("_resolved_references"); - referenceMap = type.getAddressField("_reference_map"); + resolved_klasses = type.getAddressField("_resolved_klasses"); headerSize = type.getSize(); elementSize = 0; // fetch constants: @@ -103,10 +107,9 @@ public class ConstantPool extends Metadata implements ClassConstants { private static AddressField tags; private static AddressField operands; private static AddressField cache; + private static AddressField resolved_klasses; private static MetadataField poolHolder; private static CIntField length; // number of elements in oop - private static AddressField resolvedReferences; - private static AddressField referenceMap; private static long headerSize; private static long elementSize; @@ -124,17 +127,14 @@ public class ConstantPool extends Metadata implements ClassConstants { public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); } public int getLength() { return (int)length.getValue(getAddress()); } public Oop getResolvedReferences() { - Address handle = resolvedReferences.getValue(getAddress()); - if (handle != null) { - // Load through the handle - OopHandle refs = handle.getOopHandleAt(0); - return VM.getVM().getObjectHeap().newOop(refs); - } - return null; + return getCache().getResolvedReferences(); + } + public KlassArray getResolvedKlasses() { + return new KlassArray(resolved_klasses.getValue(getAddress())); } public U2Array referenceMap() { - return new U2Array(referenceMap.getValue(getAddress())); + return getCache().referenceMap(); } public int objectToCPIndex(int index) { @@ -165,6 +165,16 @@ public class ConstantPool extends Metadata implements ClassConstants { return new CPSlot(getAddressAtRaw(index)); } + public CPKlassSlot getKlassSlotAt(long index) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(getTagAt(index).isUnresolvedKlass() || getTagAt(index).isKlass(), "Corrupted constant pool"); + } + int value = getIntAt(index); + int name_index = extractHighShortFromInt(value); + int resolved_klass_index = extractLowShortFromInt(value); + return new CPKlassSlot(name_index, resolved_klass_index); + } + public Address getAddressAtRaw(long index) { return getAddress().getAddressAt(indexOffset(index)); } @@ -315,16 +325,14 @@ public class ConstantPool extends Metadata implements ClassConstants { // returns null, if not resolved. public Klass getKlassAt(int which) { if( ! getTagAt(which).isKlass()) return null; - return (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(which)); + int resolved_klass_index = getKlassSlotAt(which).getResolvedKlassIndex(); + KlassArray resolved_klasses = getResolvedKlasses(); + return resolved_klasses.getAt(resolved_klass_index); } public Symbol getKlassNameAt(int which) { - CPSlot entry = getSlotAt(which); - if (entry.isResolved()) { - return entry.getKlass().getName(); - } else { - return entry.getSymbol(); - } + int name_index = getKlassSlotAt(which).getNameIndex(); + return getSymbolAt(name_index); } public Symbol getUnresolvedStringAt(int which) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java index 3ac3ced3615..64fd3af0310 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -51,6 +51,8 @@ public class ConstantPoolCache extends Metadata { elementSize = elType.getSize(); length = new CIntField(type.getCIntegerField("_length"), 0); intSize = VM.getVM().getObjectHeap().getIntSize(); + resolvedReferences = type.getAddressField("_resolved_references"); + referenceMap = type.getAddressField("_reference_map"); } public ConstantPoolCache(Address addr) { @@ -65,7 +67,8 @@ public class ConstantPoolCache extends Metadata { private static long elementSize; private static CIntField length; private static long intSize; - + private static AddressField resolvedReferences; + private static AddressField referenceMap; public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } @@ -100,4 +103,18 @@ public class ConstantPoolCache extends Metadata { entry.iterateFields(visitor); } } + + public Oop getResolvedReferences() { + Address handle = resolvedReferences.getValue(getAddress()); + if (handle != null) { + // Load through the handle + OopHandle refs = handle.getOopHandleAt(0); + return VM.getVM().getObjectHeap().newOop(refs); + } + return null; + } + + public U2Array referenceMap() { + return new U2Array(referenceMap.getValue(getAddress())); + } }; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 742ec9a32e0..81f1aa78daf 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -516,15 +516,7 @@ public class InstanceKlass extends Klass { if (ioff != 0) { // only look at classes that are already loaded // since we are looking for the flags for our self. - ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff); - Symbol name = null; - if (classInfo.isResolved()) { - name = classInfo.getKlass().getName(); - } else if (classInfo.isUnresolved()) { - name = classInfo.getSymbol(); - } else { - throw new RuntimeException("should not reach here"); - } + Symbol name = getConstants().getKlassNameAt(ioff); if (name.equals(getName())) { // This is really a member class @@ -571,7 +563,6 @@ public class InstanceKlass extends Klass { // 'ioff' can be zero. // refer to JVM spec. section 4.7.5. if (ioff != 0) { - ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff); Symbol innerName = getConstants().getKlassNameAt(ioff); Symbol myname = getName(); int ooff = innerClassList.at(i + @@ -592,15 +583,7 @@ public class InstanceKlass extends Klass { } } } else { - ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff); - Symbol outerName = null; - if (oclassInfo.isResolved()) { - outerName = oclassInfo.getKlass().getName(); - } else if (oclassInfo.isUnresolved()) { - outerName = oclassInfo.getSymbol(); - } else { - throw new RuntimeException("should not reach here"); - } + Symbol outerName = getConstants().getKlassNameAt(ooff); // include only if current class is outer class. if (outerName.equals(myname) && innerName.equals(sym)) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java index a5c811b8280..17d24d4f145 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -630,11 +630,12 @@ public class HTMLGenerator implements /* imports */ ClassConstants { buf.beginTag("ul"); for (int exp = 0; exp < exceptions.length; exp++) { short cpIndex = (short) exceptions[exp].getClassCPIndex(); - ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); - if (obj.isUnresolved()) { - buf.li((obj.getSymbol()).asString().replace('/', '.')); + ConstantTag tag = cpool.getTagAt(cpIndex); + if (tag.isUnresolvedKlass()) { + buf.li(cpool.getKlassNameAt(cpIndex).asString().replace('/', '.')); } else { - buf.li(genKlassLink((InstanceKlass)obj.getKlass())); + Klass k = cpool.getKlassAt(cpIndex); + buf.li(genKlassLink((InstanceKlass)k)); } } buf.endTag("ul"); @@ -766,13 +767,14 @@ public class HTMLGenerator implements /* imports */ ClassConstants { buf.cell(Integer.toString(exceptionTable[e].getEndPC())); buf.cell(Integer.toString(exceptionTable[e].getHandlerPC())); short cpIndex = (short) exceptionTable[e].getCatchTypeIndex(); - ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex); - if (obj == null) { - buf.cell("Any"); - } else if (obj.isUnresolved()) { - buf.cell(obj.getSymbol().asString().replace('/', '.')); + ConstantTag tag = cpIndex == 0? null : cpool.getTagAt(cpIndex); + if (tag == null) { + buf.cell("Any"); + } else if (tag.isUnresolvedKlass()) { + buf.cell(cpool.getKlassNameAt(cpIndex).asString().replace('/', '.')); } else { - buf.cell(genKlassLink((InstanceKlass)obj.getKlass())); + Klass k = cpool.getKlassAt(cpIndex); + buf.cell(genKlassLink((InstanceKlass)k)); } buf.endTag("tr"); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java index fa13cab041e..fc1c4341e8c 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2012, 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 sun.jvm.hotspot.utilities; import java.util.Observable; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java index 09cf93cd78c..5737c5f668f 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2012, 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 sun.jvm.hotspot.utilities; import java.util.Observable; diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index a5c0c7c3b62..944d7e58ca1 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -459,9 +459,9 @@ final class CompilerToVM { native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method); /** - * Determines if {@code method} should not be inlined or compiled. + * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM. */ - native void doNotInlineOrCompile(HotSpotResolvedJavaMethodImpl method); + native void setNotInlineableOrCompileable(HotSpotResolvedJavaMethodImpl method); /** * Invalidates the profiling information for {@code method} and (re)initializes it such that diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java index c6dd6f2410b..60ae8f4a764 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -52,7 +52,8 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv static final ResolvedJavaType lambdaFormType; static final ResolvedJavaField methodHandleFormField; static final ResolvedJavaField lambdaFormVmentryField; - static final HotSpotResolvedJavaField memberNameVmtargetField; + static final ResolvedJavaField methodField; + static final HotSpotResolvedJavaField vmtargetField; /** * Search for an instance field with the given name in a class. @@ -88,7 +89,10 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv lambdaFormType = resolveType("java.lang.invoke.LambdaForm"); methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType); lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType); - memberNameVmtargetField = (HotSpotResolvedJavaField) findFieldInClass(memberNameType, "vmtarget", resolveType(long.class)); + ResolvedJavaType methodType = resolveType("java.lang.invoke.ResolvedMethodName"); + methodField = findFieldInClass(memberNameType, "method", methodType); + vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(HotSpotJVMCIRuntime.getHostWordKind().toJavaClass())); + } catch (Throwable ex) { throw new JVMCIError(ex); } @@ -139,24 +143,30 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm); assert memberName.isNonNull(); } - return getTargetMethod(memberName); + JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName); + return getTargetMethod(method); } @Override public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) { - return getTargetMethod(memberName); - } - - /** - * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName. - */ - private static ResolvedJavaMethod getTargetMethod(JavaConstant memberName) { if (memberName.isNull()) { return null; } + JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName); + return getTargetMethod(method); + } - Object object = ((HotSpotObjectConstantImpl) memberName).object(); - /* Read the ResolvedJavaMethod from the injected field MemberName.vmtarget */ - return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset()); + /** + * Returns the {@link ResolvedJavaMethod} for the method of a java.lang.invoke.MemberName. + */ + private static ResolvedJavaMethod getTargetMethod(JavaConstant method) { + if (method == null) { + // If readFieldValue returns NULL the type was wrong + throw new IllegalArgumentException("unexpected type for memberName"); + } + + Object object = ((HotSpotObjectConstantImpl) method).object(); + /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */ + return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.vmtargetField.offset()); } } diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java index af75f81a2ff..5a71dd513de 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java @@ -57,9 +57,9 @@ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod { boolean hasReservedStackAccess(); /** - * Manually adds a DontInline annotation to this method. + * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM. */ - void setNotInlineable(); + void setNotInlineableOrCompileable(); /** * Returns true if this method is one of the special methods that is ignored by security stack diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index f831db4c5f9..51b556ae038 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -318,10 +318,10 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp } /** - * Manually adds a DontInline annotation to this method. + * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM. */ - public void setNotInlineable() { - compilerToVM().doNotInlineOrCompile(this); + public void setNotInlineableOrCompileable() { + compilerToVM().setNotInlineableOrCompileable(this); } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py index b7f897c0862..f3b85008ff7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py +++ b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py @@ -47,6 +47,7 @@ suite = { "sha1" : "476d9a44cd19d6b55f81571077dfa972a4f8a083", "bootClassPathAgent" : "true", }, + "ASM5" : { "sha1" : "0da08b8cce7bbf903602a25a3a163ae252435795", "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-5.0.4.jar"], @@ -60,15 +61,29 @@ suite = { }, "projects" : { - - # ------------- Graal ------------- - "org.graalvm.compiler.common" : { + # -------------- SDK -------------- + "org.graalvm.options" : { "subDir" : "share/classes", "sourceDirs" : ["src"], - "checkstyle" : "org.graalvm.compiler.graph", + "dependencies" : [], + "uses" : [], + "exports" : [ + "", # exports all packages containing package-info.java + ], + "checkstyle" : "org.graalvm.api.word", "javaCompliance" : "1.8", - "workingSets" : "API,Graal", + "workingSets" : "API,SDK", }, + "org.graalvm.api.word" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [], + "checkstyle" : "org.graalvm.api.word", + "javaCompliance" : "1.8", + "workingSets" : "API,SDK", + }, + + # ------------- Graal ------------- "org.graalvm.compiler.serviceprovider" : { "subDir" : "share/classes", @@ -90,9 +105,11 @@ suite = { "org.graalvm.compiler.options" : { "subDir" : "share/classes", - "dependencies" : ["JVMCI_SERVICES", "JVMCI_API"], + "dependencies" : ["JVMCI_SERVICES", "JVMCI_API", "org.graalvm.util"], "sourceDirs" : ["src"], + "dependencies" : ["org.graalvm.util"], "checkstyle" : "org.graalvm.compiler.graph", + "uses" : ["org.graalvm.compiler.options.OptionDescriptors"], "javaCompliance" : "1.8", "workingSets" : "Graal", }, @@ -124,6 +141,11 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "checkstyle" : "org.graalvm.compiler.graph", + "uses" : [ + "org.graalvm.compiler.debug.DebugConfigCustomizer", + "org.graalvm.compiler.debug.DebugInitializationParticipant", + "org.graalvm.compiler.debug.TTYStreamProvider", + ], "dependencies" : [ "JVMCI_API", "org.graalvm.compiler.serviceprovider", @@ -151,7 +173,6 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.graph", - "org.graalvm.compiler.common", ], "annotationProcessors" : ["GRAAL_SERVICEPROVIDER_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", @@ -159,7 +180,7 @@ suite = { "workingSets" : "Graal", }, - "org.graalvm.compiler.api.collections" : { + "org.graalvm.util" : { "subDir" : "share/classes", "sourceDirs" : ["src"], "checkstyle" : "org.graalvm.compiler.graph", @@ -167,6 +188,18 @@ suite = { "workingSets" : "API,Graal", }, + "org.graalvm.util.test" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "mx:JUNIT", + "org.graalvm.util", + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "workingSets" : "API,Graal", + }, + "org.graalvm.compiler.api.directives" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -227,8 +260,14 @@ suite = { "JVMCI_HOTSPOT", "org.graalvm.compiler.api.runtime", "org.graalvm.compiler.replacements", + "org.graalvm.compiler.printer", "org.graalvm.compiler.runtime", ], + "imports" : [ + # All other internal packages are exported dynamically - + # see org.graalvm.compiler.hotspot.HotSpotGraalJVMCIServiceLocator + "jdk.internal.module", + ], "checkstyle" : "org.graalvm.compiler.graph", "annotationProcessors" : [ "GRAAL_NODEINFO_PROCESSOR", @@ -372,7 +411,6 @@ suite = { "dependencies" : [ "org.graalvm.compiler.nodeinfo", "org.graalvm.compiler.core.common", - "org.graalvm.compiler.api.collections", ], "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -401,6 +439,7 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "JVMCI_API", + "org.graalvm.compiler.core.common" ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -411,7 +450,6 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ - "org.graalvm.compiler.debug", "org.graalvm.compiler.asm", ], "checkstyle" : "org.graalvm.compiler.graph", @@ -434,9 +472,7 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ - "org.graalvm.compiler.debug", "org.graalvm.compiler.asm", - "org.graalvm.compiler.common" ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -688,7 +724,6 @@ suite = { "org.graalvm.compiler.bytecode", "org.graalvm.compiler.lir", ], - "generatedDependencies" : ["org.graalvm.compiler.serviceprovider"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -767,6 +802,18 @@ suite = { "workingSets" : "Graal", }, + "org.graalvm.compiler.loop.test" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "org.graalvm.compiler.loop", + "org.graalvm.compiler.core.test" + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "workingSets" : "Graal,Test", + }, + "org.graalvm.compiler.loop.phases" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -787,6 +834,7 @@ suite = { "org.graalvm.compiler.virtual", "org.graalvm.compiler.loop.phases", ], + "uses" : ["org.graalvm.compiler.core.match.MatchStatementSet"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -922,6 +970,7 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.debug", + "org.graalvm.api.word", ], "annotationProcessors" : ["GRAAL_OPTIONS_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", @@ -949,6 +998,7 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ + "org.graalvm.util", "mx:JUNIT", ], "checkstyle" : "org.graalvm.compiler.graph", @@ -969,6 +1019,7 @@ suite = { "JAVA_ALLOCATION_INSTRUMENTER", "ASM_TREE5", ], + "uses" : ["org.graalvm.compiler.options.OptionDescriptors"], "annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -989,21 +1040,6 @@ suite = { "findbugs" : "false", }, - # ------------- Salver ------------- - - "org.graalvm.compiler.salver" : { - "subDir" : "share/classes", - "sourceDirs" : ["src"], - "dependencies" : ["org.graalvm.compiler.phases"], - "annotationProcessors" : [ - "GRAAL_OPTIONS_PROCESSOR", - "GRAAL_SERVICEPROVIDER_PROCESSOR", - ], - "checkstyle" : "org.graalvm.compiler.graph", - "javaCompliance" : "1.8", - "workingSets" : "Graal", - }, - # ------------- AOT ------------- "jdk.tools.jaotc" : { @@ -1133,7 +1169,6 @@ suite = { "org.graalvm.compiler.replacements.amd64", "org.graalvm.compiler.core.sparc", "org.graalvm.compiler.replacements.sparc", - "org.graalvm.compiler.salver", ], "distDependencies" : [ "GRAAL_API", @@ -1257,7 +1292,6 @@ suite = { "org.graalvm.compiler.replacements.amd64", "org.graalvm.compiler.core.sparc", "org.graalvm.compiler.replacements.sparc", - "org.graalvm.compiler.salver", "org.graalvm.compiler.hotspot.aarch64", "org.graalvm.compiler.hotspot.amd64", "org.graalvm.compiler.hotspot.sparc", diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java index 783eef09fa5..3410829a8d0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java @@ -39,6 +39,8 @@ module jdk.internal.vm.compiler { uses org.graalvm.compiler.debug.TTYStreamProvider; 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.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; exports org.graalvm.compiler.api.directives to jdk.aot; @@ -69,4 +71,5 @@ module jdk.internal.vm.compiler { exports org.graalvm.compiler.runtime to jdk.aot; exports org.graalvm.compiler.replacements to jdk.aot; exports org.graalvm.compiler.word to jdk.aot; + exports org.graalvm.word to jdk.aot; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java deleted file mode 100644 index f8c00882bb7..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.api.collections; - -import java.util.Map; -import java.util.Set; - -/** - * A factory for creating collections. - */ -public interface CollectionsProvider { - - /** - * Creates a set that uses reference-equality in place of object-equality when comparing - * entries. - */ - Set newIdentitySet(); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - */ - Map newIdentityMap(); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - * - * @param expectedMaxSize the expected maximum size of the map - */ - Map newIdentityMap(int expectedMaxSize); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - * - * @param initFrom the returned map is populated with the entries in this map - */ - Map newIdentityMap(Map initFrom); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java deleted file mode 100644 index 03bd8a7804d..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.api.directives.test; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@SuppressWarnings("try") -public class AllocationInstrumentationTest extends GraalCompilerTest { - - private TinyInstrumentor instrumentor; - - public AllocationInstrumentationTest() { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod"); - method.setNotInlineable(); - - try { - instrumentor = new TinyInstrumentor(AllocationInstrumentationTest.class, "instrumentation"); - } catch (IOException e) { - Assert.fail("unable to initialize the instrumentor: " + e); - } - } - - public static class ClassA { - // This method should be marked as not inlineable - public void notInlinedMethod() { - } - } - - public static boolean allocationWasExecuted; - - private static void resetFlag() { - allocationWasExecuted = false; - } - - static void instrumentation() { - GraalDirectives.instrumentationBeginForPredecessor(); - allocationWasExecuted = true; - GraalDirectives.instrumentationEnd(); - } - - public static void notEscapeSnippet() { - @SuppressWarnings("unused") - ClassA a = new ClassA(); // a does not escape - } - - @Test - public void testNotEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "notEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "notEscapeSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet does not escape and will be optimized away. We expect - // the instrumentation is removed. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertFalse("allocation should not take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void mustEscapeSnippet() { - ClassA a = new ClassA(); - a.notInlinedMethod(); // a escapses - } - - @Test - public void testMustEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "mustEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "mustEscapeSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet escapes. We expect the instrumentation is preserved. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertTrue("allocation should take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void partialEscapeSnippet(boolean condition) { - ClassA a = new ClassA(); - - if (condition) { - a.notInlinedMethod(); // a escapes in the then-clause - } - } - - @Test - public void testPartialEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "partialEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "partialEscapeSnippet"); - executeExpected(method, null, true); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet escapes in the then-clause, and will be relocated to - // this branch. We expect the instrumentation follows and will only be effective when - // the then-clause is taken. - InstalledCode code = getCode(method); - code.executeVarargs(false); - Assert.assertFalse("allocation should not take place", allocationWasExecuted); - code.executeVarargs(true); - Assert.assertTrue("allocation should take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java index 91a14d1630d..d85e18ddf66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java @@ -70,7 +70,7 @@ public class DeoptimizeDirectiveTest extends GraalCompilerTest { Result actual; try { actual = new Result(code.executeVarargs(), null); - } catch (Throwable e) { + } catch (Exception e) { actual = new Result(null, e); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java deleted file mode 100644 index 48a1f107320..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.api.directives.test; - -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class IsMethodInlineDirectiveTest extends GraalCompilerTest { - - public IsMethodInlineDirectiveTest() { - HotSpotResolvedJavaMethod calleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeSnippet"); - calleeSnippet.shouldBeInlined(); - - HotSpotResolvedJavaMethod calleeWithInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeWithInstrumentationSnippet"); - calleeWithInstrumentationSnippet.shouldBeInlined(); - } - - public static boolean rootMethodSnippet() { - return GraalDirectives.isMethodInlined(); - } - - @SuppressWarnings("try") - @Test - public void testRootMethod() { - ResolvedJavaMethod method = getResolvedJavaMethod("rootMethodSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target method is not inlined. We expect the result to be false. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(false, null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static boolean calleeSnippet() { - return GraalDirectives.isMethodInlined(); - } - - public static boolean callerSnippet() { - return calleeSnippet(); - } - - @Test - public void testInlinedCallee() { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // calleeSnippet will be inlined. We expect the result to be true. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(true, null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - static boolean isCalleeInlined; - static boolean isCallerInlined; - - public static void calleeWithInstrumentationSnippet() { - GraalDirectives.instrumentationBegin(); - isCalleeInlined = GraalDirectives.isMethodInlined(); - GraalDirectives.instrumentationEnd(); - } - - public static void callerSnippet1() { - calleeWithInstrumentationSnippet(); - - GraalDirectives.instrumentationBegin(); - isCallerInlined = GraalDirectives.isMethodInlined(); - GraalDirectives.instrumentationEnd(); - } - - @SuppressWarnings("try") - @Test - public void testInlinedCalleeWithInstrumentation() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1"); - executeExpected(method, null); // ensure the method is fully resolved - isCalleeInlined = false; - isCallerInlined = false; - // calleeWithInstrumentationSnippet will be inlined. We expect the flag1 set in - // calleeWithInstrumentationSnippet to be true, and the flag2 set in callerSnippet1 to - // be false. - InstalledCode code = getCode(method); - code.executeVarargs(); - assertTrue("calleWithInstrumentationSnippet should be inlined", isCalleeInlined); - assertFalse("callerSnippet1 should not be inlined", isCallerInlined); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java deleted file mode 100644 index 244e2d620cc..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.api.directives.test; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@SuppressWarnings("try") -public class LockInstrumentationTest extends GraalCompilerTest { - - private TinyInstrumentor instrumentor; - - public LockInstrumentationTest() { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod"); - method.setNotInlineable(); - - try { - instrumentor = new TinyInstrumentor(LockInstrumentationTest.class, "instrumentation"); - } catch (IOException e) { - Assert.fail("unable to initialize the instrumentor: " + e); - } - } - - public static class ClassA { - - // This method should be marked as not inlineable - public void notInlinedMethod() { - } - - } - - public static final Object lock = new Object(); - public static boolean lockAfterCheckPoint; - public static boolean checkpoint; - - private static void resetFlags() { - lockAfterCheckPoint = false; - checkpoint = false; - } - - static void instrumentation() { - GraalDirectives.instrumentationBeginForPredecessor(); - lockAfterCheckPoint = checkpoint; - GraalDirectives.instrumentationEnd(); - } - - public static void lockSnippet() { - synchronized (lock) { - checkpoint = true; - ClassA a = new ClassA(); - a.notInlinedMethod(); - } - } - - @Test - public void testLock() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(LockInstrumentationTest.class, "lockSnippet", Opcodes.MONITORENTER); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "lockSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlags(); - // The monitorenter anchors. We expect the instrumentation set the flag before passing - // the checkpoint. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertFalse("expected lock was performed before checkpoint", lockAfterCheckPoint); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void postponeLockSnippet() { - ClassA a = new ClassA(); - - synchronized (a) { - checkpoint = true; - a.notInlinedMethod(); - } - - } - - @Test - public void testNonEscapeLock() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(LockInstrumentationTest.class, "postponeLockSnippet", Opcodes.MONITORENTER); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "postponeLockSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlags(); - // The lock in the snippet will be relocated before the invocation to - // notInlinedMethod(), i.e., after the checkpoint. We expect the instrumentation follows - // and flag will be set to true. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertTrue("expected lock was performed after checkpoint", lockAfterCheckPoint); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java index fe5ef07bcc1..311aabba0b9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java @@ -22,15 +22,16 @@ */ package org.graalvm.compiler.api.directives.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode; +import org.junit.Assert; +import org.junit.Test; public class ProbabilityDirectiveTest extends GraalCompilerTest { @@ -55,9 +56,21 @@ public class ProbabilityDirectiveTest extends GraalCompilerTest { Assert.assertEquals("IfNode count", 1, ifNodes.count()); IfNode ifNode = ifNodes.first(); - AbstractBeginNode trueSuccessor = ifNode.trueSuccessor(); - Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(trueSuccessor), 0); + AbstractBeginNode oneSuccessor; + if (returnValue(ifNode.trueSuccessor()) == 1) { + oneSuccessor = ifNode.trueSuccessor(); + } else { + assert returnValue(ifNode.falseSuccessor()) == 1; + oneSuccessor = ifNode.falseSuccessor(); + } + Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(oneSuccessor), 0); return true; } + + private static int returnValue(AbstractBeginNode b) { + ControlFlowAnchorNode anchor = (ControlFlowAnchorNode) b.next(); + ReturnNode returnNode = (ReturnNode) anchor.next(); + return returnNode.result().asJavaConstant().asInt(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java deleted file mode 100644 index a22ac2edb03..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.api.directives.test; - -import java.io.ByteArrayOutputStream; -import java.lang.reflect.Method; -import java.util.Formatter; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -import com.google.monitoring.runtime.instrumentation.common.com.google.common.base.Objects; -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.printer.IdealGraphPrinter; - -import jdk.vm.ci.code.CodeCacheProvider; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class RootNameDirectiveTest extends GraalCompilerTest { - - public RootNameDirectiveTest() { - HotSpotResolvedJavaMethod rootNameAtCalleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameAtCalleeSnippet"); - rootNameAtCalleeSnippet.shouldBeInlined(); - - HotSpotResolvedJavaMethod rootNameWithinInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameWithinInstrumentationSnippet"); - rootNameWithinInstrumentationSnippet.shouldBeInlined(); - } - - private static String toString(ResolvedJavaMethod method) { - return method.getDeclaringClass().toJavaName() + "." + method.getName() + method.getSignature().toMethodDescriptor(); - } - - public static String rootNameSnippet() { - return GraalDirectives.rootName(); - } - - @Test - public void testRootName() { - ResolvedJavaMethod method = getResolvedJavaMethod("rootNameSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target snippet is already the root method. We expect the name of the target snippet - // is returned. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(toString(method), null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static String rootNameAtCalleeSnippet() { - return GraalDirectives.rootName(); - } - - public static String callerSnippet() { - return rootNameAtCalleeSnippet(); - } - - @Test - public void testRootNameAtCallee() { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target snippet is the compilation root of rootNameAtCalleeSnippet() because the later - // will be inlined. We expect the name of the target snippet is returned. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(toString(method), null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - static String rootNameInCallee; - static String rootNameInCaller; - - @BytecodeParserForceInline - public static void rootNameWithinInstrumentationSnippet() { - GraalDirectives.instrumentationBegin(); - rootNameInCallee = GraalDirectives.rootName(); - GraalDirectives.instrumentationEnd(); - } - - public static void callerSnippet1() { - rootNameWithinInstrumentationSnippet(); - - GraalDirectives.instrumentationBegin(); - rootNameInCaller = GraalDirectives.rootName(); - GraalDirectives.instrumentationEnd(); - } - - @SuppressWarnings("try") - private void assertEquals(StructuredGraph graph, InstalledCode code, Object expected, Object actual) { - if (!Objects.equal(expected, actual)) { - Formatter buf = new Formatter(); - - try (Scope s = Debug.sandbox("PrintingGraph", null)) { - Map properties = new HashMap<>(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - IdealGraphPrinter printer = new IdealGraphPrinter(baos, true, getSnippetReflection()); - printer.beginGroup("RootNameDirectiveTest", "RootNameDirectiveTest", graph.method(), -1, null); - properties.put("graph", graph.toString()); - properties.put("scope", Debug.currentScope()); - printer.print(graph, graph.method().format("%H.%n(%p)"), properties); - printer.endGroup(); - printer.close(); - buf.format("-- Graph -- %n%s", baos.toString()); - } catch (Throwable e) { - buf.format("%nError printing graph: %s", e); - } - try { - CodeCacheProvider codeCache = getCodeCache(); - Method disassemble = codeCache.getClass().getMethod("disassemble", InstalledCode.class); - buf.format("%n-- Code -- %n%s", disassemble.invoke(codeCache, code)); - } catch (NoSuchMethodException e) { - // Not a HotSpotCodeCacheProvider - } catch (Exception e) { - buf.format("%nError disassembling code: %s", e); - } - Assert.assertEquals(buf.toString(), expected, actual); - } - } - - @SuppressWarnings("try") - @Test - public void testRootNameWithinInstrumentationAtCallee() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1"); - executeExpected(method, null); // ensure the method is fully resolved - rootNameInCallee = null; - rootNameInCaller = null; - // We expect both rootName1 and rootName2 are set to the name of the target snippet. - StructuredGraph graph = parseForCompile(method); - InstalledCode code = getCode(method, graph); - code.executeVarargs(); - assertEquals(graph, code, toString(method), rootNameInCallee); - assertEquals(graph, code, rootNameInCallee, rootNameInCaller); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java deleted file mode 100644 index d8cf15a17fb..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.api.directives.test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.graalvm.compiler.test.ExportingClassLoader; - -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode; -import jdk.internal.org.objectweb.asm.tree.ClassNode; -import jdk.internal.org.objectweb.asm.tree.IincInsnNode; -import jdk.internal.org.objectweb.asm.tree.InsnList; -import jdk.internal.org.objectweb.asm.tree.JumpInsnNode; -import jdk.internal.org.objectweb.asm.tree.LabelNode; -import jdk.internal.org.objectweb.asm.tree.LineNumberNode; -import jdk.internal.org.objectweb.asm.tree.MethodNode; -import jdk.internal.org.objectweb.asm.tree.VarInsnNode; - -/** - * The {@code TinyInstrumentor} is a bytecode instrumentor using ASM bytecode manipulation - * framework. It injects given code snippet into a target method and creates a temporary class as - * the container. Because the target method is cloned into the temporary class, it is required that - * the target method is public static. Any referred method/field in the target method or the - * instrumentation snippet should be made public as well. - */ -public class TinyInstrumentor implements Opcodes { - - private InsnList instrumentationInstructions; - private int instrumentationMaxLocal; - - /** - * Create a instrumentor with a instrumentation snippet. The snippet is specified with the given - * class {@code instrumentationClass} and the given method name {@code methodName}. - */ - public TinyInstrumentor(Class instrumentationClass, String methodName) throws IOException { - MethodNode instrumentationMethod = getMethodNode(instrumentationClass, methodName); - assert instrumentationMethod != null; - assert (instrumentationMethod.access | ACC_STATIC) != 0; - assert "()V".equals(instrumentationMethod.desc); - instrumentationInstructions = cloneInstructions(instrumentationMethod.instructions); - instrumentationMaxLocal = instrumentationMethod.maxLocals; - // replace return instructions with a goto unless there is a single return at the end. In - // that case, simply remove the return. - List returnInstructions = new ArrayList<>(); - for (AbstractInsnNode instruction : selectAll(instrumentationInstructions)) { - if (instruction instanceof LineNumberNode) { - instrumentationInstructions.remove(instruction); - } else if (instruction.getOpcode() == RETURN) { - returnInstructions.add(instruction); - } - } - LabelNode exit = new LabelNode(); - if (returnInstructions.size() == 1) { - AbstractInsnNode returnInstruction = returnInstructions.get(0); - if (instrumentationInstructions.getLast() != returnInstruction) { - instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit)); - } - instrumentationInstructions.remove(returnInstruction); - } else { - for (AbstractInsnNode returnInstruction : returnInstructions) { - instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit)); - instrumentationInstructions.remove(returnInstruction); - } - } - instrumentationInstructions.add(exit); - } - - /** - * @return a {@link MethodNode} called {@code methodName} in the given class. - */ - private static MethodNode getMethodNode(Class clazz, String methodName) throws IOException { - ClassReader classReader = new ClassReader(clazz.getName()); - ClassNode classNode = new ClassNode(); - classReader.accept(classNode, ClassReader.SKIP_FRAMES); - - for (MethodNode methodNode : classNode.methods) { - if (methodNode.name.equals(methodName)) { - return methodNode; - } - } - return null; - } - - /** - * Create a {@link ClassNode} with empty constructor. - */ - private static ClassNode emptyClass(String name) { - ClassNode classNode = new ClassNode(); - classNode.visit(52, ACC_SUPER | ACC_PUBLIC, name.replace('.', '/'), null, "java/lang/Object", new String[]{}); - - MethodVisitor mv = classNode.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - return classNode; - } - - /** - * Helper method for iterating the given {@link InsnList}. - */ - private static Iterable selectAll(InsnList instructions) { - return new Iterable() { - @Override - public Iterator iterator() { - return instructions.iterator(); - } - }; - } - - /** - * Make a clone of the given {@link InsnList}. - */ - private static InsnList cloneInstructions(InsnList instructions) { - Map labelMap = new HashMap<>(); - for (AbstractInsnNode instruction : selectAll(instructions)) { - if (instruction instanceof LabelNode) { - LabelNode clone = new LabelNode(new Label()); - LabelNode original = (LabelNode) instruction; - labelMap.put(original, clone); - } - } - InsnList clone = new InsnList(); - for (AbstractInsnNode insn : selectAll(instructions)) { - clone.add(insn.clone(labelMap)); - } - return clone; - } - - /** - * Shifts all local variable slot references by a specified amount. - */ - private static void shiftLocalSlots(InsnList instructions, int offset) { - for (AbstractInsnNode insn : selectAll(instructions)) { - if (insn instanceof VarInsnNode) { - VarInsnNode varInsn = (VarInsnNode) insn; - varInsn.var += offset; - - } else if (insn instanceof IincInsnNode) { - IincInsnNode iincInsn = (IincInsnNode) insn; - iincInsn.var += offset; - } - } - } - - /** - * Instrument the target method specified by the class {@code targetClass} and the method name - * {@code methodName}. For each occurrence of the {@code opcode}, the instrumentor injects a - * copy of the instrumentation snippet. - */ - public Class instrument(Class targetClass, String methodName, int opcode) throws IOException, ClassNotFoundException { - return instrument(targetClass, methodName, opcode, true); - } - - public Class instrument(Class targetClass, String methodName, int opcode, boolean insertAfter) throws IOException, ClassNotFoundException { - // create a container class - String className = targetClass.getName() + "$$" + methodName; - ClassNode classNode = emptyClass(className); - // duplicate the target method and add to the container class - MethodNode methodNode = getMethodNode(targetClass, methodName); - MethodNode newMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, methodNode.exceptions.toArray(new String[methodNode.exceptions.size()])); - methodNode.accept(newMethodNode); - classNode.methods.add(newMethodNode); - // perform bytecode instrumentation - for (AbstractInsnNode instruction : selectAll(newMethodNode.instructions)) { - if (instruction.getOpcode() == opcode) { - InsnList instrumentation = cloneInstructions(instrumentationInstructions); - shiftLocalSlots(instrumentation, newMethodNode.maxLocals); - newMethodNode.maxLocals += instrumentationMaxLocal; - if (insertAfter) { - newMethodNode.instructions.insert(instruction, instrumentation); - } else { - newMethodNode.instructions.insertBefore(instruction, instrumentation); - } - } - } - // dump a byte array and load the class with a dedicated loader to separate the namespace - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - classNode.accept(classWriter); - byte[] bytes = classWriter.toByteArray(); - return new Loader(className, bytes).findClass(className); - } - - private static class Loader extends ExportingClassLoader { - - private String className; - private byte[] bytes; - - Loader(String className, byte[] bytes) { - super(TinyInstrumentor.class.getClassLoader()); - this.className = className; - this.bytes = bytes; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - if (name.equals(className)) { - return defineClass(name, bytes, 0, bytes.length); - } else { - return super.findClass(name); - } - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java index 35bb6686845..aa23c861a4a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.api.directives; -import java.nio.charset.Charset; - // JaCoCo Exclude /** @@ -367,67 +365,4 @@ public final class GraalDirectives { */ public static void ensureVirtualizedHere(@SuppressWarnings("unused") Object object) { } - - /** - * Marks the beginning of an instrumentation boundary. The instrumentation code will be folded - * during compilation and will not affect inlining heuristics regarding graph size except one on - * compiled low-level graph size (e.g., {@code GraalOptions.SmallCompiledLowLevelGraphSize}). - */ - public static void instrumentationBegin() { - } - - /** - * Marks the beginning of an instrumentation boundary and associates the instrumentation with - * the preceding bytecode. If the instrumented instruction is {@code new}, then instrumentation - * will adapt to optimizations concerning allocation, and only be executed if allocation really - * happens. - * - * Example (the instrumentation is associated with {@code new}): - * - *
- * - *
-     *  0  new java.lang.Object
-     *  3  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationBeginForPredecessor() : void
-     *  6  invokestatic AllocationProfiler.countActualAllocation() : void
-     *  9  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationEnd() : void
-     * 12  invokespecial java.lang.Object()
-     * 
- * - *
- * - * @see #instrumentationBegin() - */ - public static void instrumentationBeginForPredecessor() { - } - - /** - * Marks the end of the instrumentation boundary. - * - * @see #instrumentationBegin() - */ - public static void instrumentationEnd() { - } - - /** - * @return true if the enclosing method is inlined. - */ - public static boolean isMethodInlined() { - return false; - } - - private static final Charset UTF8 = Charset.forName("UTF-8"); - - /** - * @return the name of the root method for the current compilation task. If the enclosing method - * is inlined, it returns the name of the method into which it is inlined. - */ - public static String rootName() { - return new String(rawRootName(), UTF8); - } - - public static byte[] rawRootName() { - return new byte[0]; - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java index 8b904f36561..08cbae1ce6c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java @@ -54,4 +54,13 @@ public @interface Snippet { @Target(ElementType.PARAMETER) public @interface ConstantParameter { } + + /** + * Denotes a snippet parameter that will bound to a non-null value during snippet template + * instantiation. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + public @interface NonNullParameter { + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java index 82268194cbd..034ee954987 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java @@ -24,13 +24,13 @@ package org.graalvm.compiler.api.test; import java.util.Formatter; +import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.api.runtime.GraalRuntime; + import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.services.Services; -import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; -import org.graalvm.compiler.api.runtime.GraalRuntime; - /** * Access point for {@linkplain #getRuntime() retrieving} the {@link GraalRuntime} instance of the * system compiler from unit tests. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java index 8bc7e55ecec..be74fd7c167 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java @@ -31,7 +31,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java index 9934218b662..9c579967920 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java @@ -226,12 +226,12 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { super.adds(size, dst, src1, src2, shiftType, imm); } @Override - protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { super.subs(size, dst, src1, src2, shiftType, imm); } @@ -261,7 +261,7 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { + public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { super.subs(size, dst, src1, src2, extendType, shiftAmt); } @@ -336,7 +336,7 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void rbit(int size, Register dst, Register src) { + public void rbit(int size, Register dst, Register src) { super.rbit(size, dst, src); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java index 31d07c5b9c0..b86b2c4e26b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.asm.aarch64; import static jdk.vm.ci.aarch64.AArch64.zr; import org.graalvm.compiler.asm.AbstractAddress; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.aarch64.AArch64; @@ -274,7 +274,7 @@ public final class AArch64Address extends AbstractAddress { /** * @return immediate in correct representation for the given addressing mode. For example in * case of addressingMode ==IMMEDIATE_UNSCALED the value will be returned - * as the 9bit signed representation. + * as the 9-bit signed representation. */ public int getImmediate() { switch (addressingMode) { @@ -282,12 +282,15 @@ public final class AArch64Address extends AbstractAddress { case IMMEDIATE_POST_INDEXED: case IMMEDIATE_PRE_INDEXED: // 9-bit signed value + assert NumUtil.isSignedNbit(9, immediate); return immediate & NumUtil.getNbitNumberInt(9); case IMMEDIATE_SCALED: // Unsigned value can be returned as-is. + assert NumUtil.isUnsignedNbit(12, immediate); return immediate; case PC_LITERAL: // 21-bit signed value, but lower 2 bits are always 0 and are shifted out. + assert NumUtil.isSignedNbit(19, immediate >> 2); return (immediate >> 2) & NumUtil.getNbitNumberInt(19); default: throw GraalError.shouldNotReachHere("Should only be called for addressing modes that use immediate values."); @@ -356,4 +359,29 @@ public final class AArch64Address extends AbstractAddress { } } + /** + * Loads an address into Register r. + * + * @param masm the macro assembler. + * @param r general purpose register. May not be null. + */ + public void lea(AArch64MacroAssembler masm, Register r) { + switch (addressingMode) { + case IMMEDIATE_UNSCALED: + if (immediate == 0 && base.equals(r)) { // it's a nop + break; + } + masm.add(64, r, base, immediate); + break; + case REGISTER_OFFSET: + masm.add(64, r, base, offset); + break; + case PC_LITERAL: { + masm.mov(r, getImmediate()); + break; + } + default: + throw GraalError.shouldNotReachHere(); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java index 02a7eb2d686..845dba7bbd6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java @@ -94,6 +94,8 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STXR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUB; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUBS; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBZ; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBNZ; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UBFM; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UDIV; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP32; @@ -111,7 +113,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import java.util.Arrays; import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.debug.GraalError; @@ -347,6 +349,11 @@ public abstract class AArch64Assembler extends Assembler { return reg.encoding << RnOffset; } + private static int maskField(int sizeInBits, int n) { + assert NumUtil.isSignedNbit(sizeInBits, n); + return n & NumUtil.getNbitNumberInt(sizeInBits); + } + /** * Enumeration of all different instruction kinds: General32/64 are the general instructions * (integer, branch, etc.), for 32-, respectively 64-bit operands. FP32/64 is the encoding for @@ -448,7 +455,7 @@ public abstract class AArch64Assembler extends Assembler { private static final int LoadStoreFpFlagOffset = 26; private static final int LoadLiteralImmeOffset = 5; - private static final int LoadStorePairOp = 0b101_0_010 << 23; + private static final int LoadStorePairOp = 0b101_0 << 26; @SuppressWarnings("unused") private static final int LoadStorePairPostIndexOp = 0b101_0_001 << 23; @SuppressWarnings("unused") private static final int LoadStorePairPreIndexOp = 0b101_0_011 << 23; private static final int LoadStorePairImm7Offset = 15; @@ -470,6 +477,8 @@ public abstract class AArch64Assembler extends Assembler { BCOND(0x54000000), CBNZ(0x01000000), CBZ(0x00000000), + TBZ(0x36000000), + TBNZ(0x37000000), B(0x00000000), BL(0x80000000), @@ -803,6 +812,82 @@ public abstract class AArch64Assembler extends Assembler { conditionalBranchInstruction(reg, imm21, generalFromSize(size), Instruction.CBZ, pos); } + /** + * Test a single bit and branch if the bit is nonzero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + */ + protected void tbnz(Register reg, int uimm6, int imm16) { + tbnz(reg, uimm6, imm16, -1); + } + + /** + * Test a single bit and branch if the bit is zero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + */ + protected void tbz(Register reg, int uimm6, int imm16) { + tbz(reg, uimm6, imm16, -1); + } + + /** + * Test a single bit and branch if the bit is nonzero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + * @param pos Position at which instruction is inserted into buffer. -1 means insert at end. + */ + protected void tbnz(Register reg, int uimm6, int imm16, int pos) { + assert reg.getRegisterCategory().equals(CPU); + assert NumUtil.isUnsignedNbit(6, uimm6); + assert NumUtil.isSignedNbit(18, imm16); + assert (imm16 & 3) == 0; + // size bit is overloaded as top bit of uimm6 bit index + int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); + // remaining 5 bits are encoded lower down + int uimm5 = uimm6 >> 1; + int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; + InstructionType type = generalFromSize(size); + int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg); + if (pos == -1) { + emitInt(encoding); + } else { + emitInt(encoding, pos); + } + } + + /** + * Test a single bit and branch if the bit is zero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + * @param pos Position at which instruction is inserted into buffer. -1 means insert at end. + */ + protected void tbz(Register reg, int uimm6, int imm16, int pos) { + assert reg.getRegisterCategory().equals(CPU); + assert NumUtil.isUnsignedNbit(6, uimm6); + assert NumUtil.isSignedNbit(18, imm16); + assert (imm16 & 3) == 0; + // size bit is overloaded as top bit of uimm6 bit index + int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); + // remaining 5 bits are encoded lower down + int uimm5 = uimm6 >> 1; + int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; + InstructionType type = generalFromSize(size); + int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg); + if (pos == -1) { + emitInt(encoding); + } else { + emitInt(encoding, pos); + } + } + private void conditionalBranchInstruction(Register reg, int imm21, InstructionType type, Instruction instr, int pos) { assert reg.getRegisterCategory().equals(CPU); int instrEncoding = instr.encoding | CompareBranchOp; @@ -978,7 +1063,9 @@ public abstract class AArch64Assembler extends Assembler { } /** - * + * Load Pair of Registers calculates an address from a base register value and an immediate + * offset, and stores two 32-bit words or two 64-bit doublewords to the calculated address, from + * two registers. */ public void ldp(int size, Register rt, Register rt2, AArch64Address address) { assert size == 32 || size == 64; @@ -996,10 +1083,18 @@ public abstract class AArch64Assembler extends Assembler { } private void loadStorePairInstruction(Instruction instr, Register rt, Register rt2, AArch64Address address, InstructionType type) { - int memop = type.encoding | instr.encoding | address.getImmediate() << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt); + int scaledOffset = maskField(7, address.getImmediateRaw()); // LDP/STP use a 7-bit scaled + // offset + int memop = type.encoding | instr.encoding | scaledOffset << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt); switch (address.getAddressingMode()) { - case IMMEDIATE_UNSCALED: - emitInt(memop | LoadStorePairOp); + case IMMEDIATE_SCALED: + emitInt(memop | LoadStorePairOp | (0b010 << 23)); + break; + case IMMEDIATE_POST_INDEXED: + emitInt(memop | LoadStorePairOp | (0b001 << 23)); + break; + case IMMEDIATE_PRE_INDEXED: + emitInt(memop | LoadStorePairOp | (0b011 << 23)); break; default: throw GraalError.shouldNotReachHere("Unhandled addressing mode: " + address.getAddressingMode()); @@ -1471,7 +1566,7 @@ public abstract class AArch64Assembler extends Assembler { * @param shiftType any type but ROR. * @param imm must be in range 0 to size - 1. */ - protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { addSubShiftedInstruction(ADDS, dst, src1, src2, shiftType, imm, generalFromSize(size)); } @@ -1499,7 +1594,7 @@ public abstract class AArch64Assembler extends Assembler { * @param shiftType any type but ROR. * @param imm must be in range 0 to size - 1. */ - protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { addSubShiftedInstruction(SUBS, dst, src1, src2, shiftType, imm, generalFromSize(size)); } @@ -1571,7 +1666,7 @@ public abstract class AArch64Assembler extends Assembler { * @param extendType defines how src2 is extended to the same size as src1. * @param shiftAmt must be in range 0 to 4. */ - protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { + public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { assert !dst.equals(sp); assert !src1.equals(zr); assert !src2.equals(sp); @@ -1786,7 +1881,7 @@ public abstract class AArch64Assembler extends Assembler { * @param dst general purpose register. May not be null, zero-register or the stackpointer. * @param src source register. May not be null, zero-register or the stackpointer. */ - protected void rbit(int size, Register dst, Register src) { + public void rbit(int size, Register dst, Register src) { dataProcessing1SourceOp(RBIT, dst, src, generalFromSize(size)); } @@ -1934,7 +2029,7 @@ public abstract class AArch64Assembler extends Assembler { * @param src2 general purpose register. May not be null or the stackpointer. * @param src3 general purpose register. May not be null or the stackpointer. */ - protected void smaddl(Register dst, Register src1, Register src2, Register src3) { + public void smaddl(Register dst, Register src1, Register src2, Register src3) { assert !dst.equals(sp); assert !src1.equals(sp); assert !src2.equals(sp); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java index 7c0d184e02c..cfe05572369 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java @@ -39,7 +39,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import org.graalvm.compiler.asm.AbstractAddress; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.aarch64.AArch64; @@ -196,6 +196,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { break; case ADD_TO_INDEX: newIndex = allowOverwrite ? index : additionalReg; + assert !newIndex.equals(sp) && !newIndex.equals(zr); if (plan.needsScratch) { mov(additionalReg, scaledDisplacement); add(signExtendIndex ? 32 : 64, newIndex, index, additionalReg); @@ -206,6 +207,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { break; case ADD_TO_BASE: newBase = allowOverwrite ? base : additionalReg; + assert !newBase.equals(sp) && !newBase.equals(zr); if (plan.needsScratch) { mov(additionalReg, displacement); add(64, newBase, base, additionalReg); @@ -411,6 +413,19 @@ public class AArch64MacroAssembler extends AArch64Assembler { assert !firstMove; } + /** + * Generates a 32-bit immediate move code sequence. The immediate may later be updated by + * HotSpot. + * + * @param dst general purpose register. May not be null, stackpointer or zero-register. + * @param imm + */ + public void movNarrowAddress(Register dst, long imm) { + assert (imm & 0xFFFF_FFFF_0000_0000L) == 0; + movz(64, dst, (int) (imm >>> 16), 16); + movk(64, dst, (int) (imm & 0xffff), 0); + } + /** * @return Number of instructions necessary to load immediate into register. */ @@ -455,6 +470,19 @@ public class AArch64MacroAssembler extends AArch64Assembler { } } + /** + * Loads a srcSize value from address into rt zero-extending it if necessary. + * + * @param srcSize size of memory read in bits. Must be 8, 16 or 32 and smaller or equal to + * targetSize. + * @param rt general purpose register. May not be null or stackpointer. + * @param address all addressing modes allowed. May not be null. + */ + @Override + public void ldr(int srcSize, Register rt, AArch64Address address) { + super.ldr(srcSize, rt, address); + } + /** * Conditional move. dst = src1 if condition else src2. * @@ -482,52 +510,47 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src1 + src2. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void add(int size, Register dst, Register src1, Register src2) { - super.add(size, dst, src1, src2, ShiftType.LSL, 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.add(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.add(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** * dst = src1 + src2 and sets condition flags. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void adds(int size, Register dst, Register src1, Register src2) { - super.adds(size, dst, src1, src2, getNopExtendType(size), 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.adds(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.adds(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** * dst = src1 - src2 and sets condition flags. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void subs(int size, Register dst, Register src1, Register src2) { - super.subs(size, dst, src1, src2, getNopExtendType(size), 0); - } - - /** - * Returns the ExtendType for the given size that corresponds to a no-op. - * - * I.e. when doing add X0, X1, X2, the actual instruction has the form add X0, X1, X2 UXTX. - * - * @param size - */ - private static ExtendType getNopExtendType(int size) { - if (size == 64) { - return ExtendType.UXTX; - } else if (size == 32) { - return ExtendType.UXTW; + if (dst.equals(sp) || src1.equals(sp)) { + super.subs(size, dst, src1, src2, ExtendType.UXTX, 0); } else { - throw GraalError.shouldNotReachHere("No-op "); + super.subs(size, dst, src1, src2, ShiftType.LSL, 0); } } @@ -535,12 +558,16 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src1 - src2. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void sub(int size, Register dst, Register src1, Register src2) { - super.sub(size, dst, src1, src2, ShiftType.LSL, 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.sub(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.sub(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** @@ -590,16 +617,26 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src + immediate. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src general purpose register. May not be null or stackpointer. - * @param immediate arithmetic immediate + * @param dst general purpose register. May not be null or zero-register. + * @param src general purpose register. May not be null or zero-register. + * @param immediate 32-bit signed int */ @Override public void add(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(zr) && !src.equals(zr)); if (immediate < 0) { sub(size, dst, src, -immediate); - } else if (!(dst.equals(src) && immediate == 0)) { - super.add(size, dst, src, immediate); + } else if (isAimm(immediate)) { + if (!(dst.equals(src) && immediate == 0)) { + super.add(size, dst, src, immediate); + } + } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) { + super.add(size, dst, src, immediate & -(1 << 12)); + super.add(size, dst, dst, immediate & ((1 << 12) - 1)); + } else { + assert !dst.equals(src); + mov(dst, immediate); + add(size, src, dst, dst); } } @@ -613,6 +650,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { */ @Override public void adds(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(sp) && !src.equals(zr)); if (immediate < 0) { subs(size, dst, src, -immediate); } else if (!(dst.equals(src) && immediate == 0)) { @@ -624,16 +662,26 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src - immediate. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src general purpose register. May not be null or stackpointer. - * @param immediate arithmetic immediate + * @param dst general purpose register. May not be null or zero-register. + * @param src general purpose register. May not be null or zero-register. + * @param immediate 32-bit signed int */ @Override public void sub(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(zr) && !src.equals(zr)); if (immediate < 0) { add(size, dst, src, -immediate); - } else if (!dst.equals(src) || immediate != 0) { - super.sub(size, dst, src, immediate); + } else if (isAimm(immediate)) { + if (!(dst.equals(src) && immediate == 0)) { + super.sub(size, dst, src, immediate); + } + } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) { + super.sub(size, dst, src, immediate & -(1 << 12)); + super.sub(size, dst, dst, immediate & ((1 << 12) - 1)); + } else { + assert !dst.equals(src); + mov(dst, immediate); + sub(size, src, dst, dst); } } @@ -647,10 +695,11 @@ public class AArch64MacroAssembler extends AArch64Assembler { */ @Override public void subs(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(sp) && !src.equals(zr)); if (immediate < 0) { adds(size, dst, src, -immediate); } else if (!dst.equals(src) || immediate != 0) { - super.sub(size, dst, src, immediate); + super.subs(size, dst, src, immediate); } } @@ -675,6 +724,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param src2 general purpose register. May not be null or the stackpointer. */ public void umulh(int size, Register dst, Register src1, Register src2) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp)); assert size == 32 || size == 64; if (size == 64) { super.umulh(dst, src1, src2); @@ -695,6 +745,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param src2 general purpose register. May not be null or the stackpointer. */ public void smulh(int size, Register dst, Register src1, Register src2) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp)); assert size == 32 || size == 64; if (size == 64) { super.smulh(dst, src1, src2); @@ -715,6 +766,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param d denominator. General purpose register. Divisor May not be null or the stackpointer. */ public void rem(int size, Register dst, Register n, Register d) { + assert (!dst.equals(sp) && !n.equals(sp) && !d.equals(sp)); // There is no irem or similar instruction. Instead we use the relation: // n % d = n - Floor(n / d) * d if nd >= 0 // n % d = n - Ceil(n / d) * d else @@ -940,16 +992,14 @@ public class AArch64MacroAssembler extends AArch64Assembler { /** * Sign-extend value from src into dst. * - * @param destSize destination register size. Has to be 32 or 64. - * @param srcSize source register size. May be 8, 16 or 32 and smaller than destSize. + * @param destSize destination register size. Must be 32 or 64. + * @param srcSize source register size. Must be smaller than destSize. * @param dst general purpose register. May not be null, stackpointer or zero-register. * @param src general purpose register. May not be null, stackpointer or zero-register. */ public void sxt(int destSize, int srcSize, Register dst, Register src) { - assert (destSize == 32 || destSize == 64) && srcSize < destSize; - assert srcSize == 8 || srcSize == 16 || srcSize == 32; - int[] srcSizeValues = {7, 15, 31}; - super.sbfm(destSize, dst, src, 0, srcSizeValues[NumUtil.log2Ceil(srcSize / 8)]); + assert (srcSize < destSize && srcSize > 0); + super.sbfm(destSize, dst, src, 0, srcSize - 1); } /** @@ -1078,6 +1128,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param y general purpose register. May not be null or stackpointer. */ public void cmp(int size, Register x, Register y) { + assert size == 32 || size == 64; super.subs(size, zr, x, y, ShiftType.LSL, 0); } @@ -1089,6 +1140,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param y comparison immediate, {@link #isComparisonImmediate(long)} has to be true for it. */ public void cmp(int size, Register x, int y) { + assert size == 32 || size == 64; if (y < 0) { super.adds(size, zr, x, -y); } else { @@ -1108,6 +1160,54 @@ public class AArch64MacroAssembler extends AArch64Assembler { super.ands(size, dst, x, y, ShiftType.LSL, 0); } + /** + * Sets overflow flag according to result of x * y. + * + * @param size register size. Has to be 32 or 64. + * @param dst general purpose register. May not be null or stack-pointer. + * @param x general purpose register. May not be null or stackpointer. + * @param y general purpose register. May not be null or stackpointer. + */ + public void mulvs(int size, Register dst, Register x, Register y) { + try (ScratchRegister sc1 = getScratchRegister(); + ScratchRegister sc2 = getScratchRegister()) { + switch (size) { + case 64: { + // Be careful with registers: it's possible that x, y, and dst are the same + // register. + Register rscratch1 = sc1.getRegister(); + Register rscratch2 = sc2.getRegister(); + mul(64, rscratch1, x, y); // Result bits 0..63 + smulh(64, rscratch2, x, y); // Result bits 64..127 + // Top is pure sign ext + subs(64, zr, rscratch2, rscratch1, ShiftType.ASR, 63); + // Copy all 64 bits of the result into dst + mov(64, dst, rscratch1); + mov(rscratch1, 0x80000000); + // Develop 0 (EQ), or 0x80000000 (NE) + cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE); + cmp(32, rscratch1, 1); + // 0x80000000 - 1 => VS + break; + } + case 32: { + Register rscratch1 = sc1.getRegister(); + smaddl(rscratch1, x, y, zr); + // Copy the low 32 bits of the result into dst + mov(32, dst, rscratch1); + subs(64, zr, rscratch1, rscratch1, ExtendType.SXTW, 0); + // NE => overflow + mov(rscratch1, 0x80000000); + // Develop 0 (EQ), or 0x80000000 (NE) + cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE); + cmp(32, rscratch1, 1); + // 0x80000000 - 1 => VS + break; + } + } + } + } + /** * When patching up Labels we have to know what kind of code to generate. */ @@ -1116,8 +1216,10 @@ public class AArch64MacroAssembler extends AArch64Assembler { BRANCH_UNCONDITIONALLY(0x1), BRANCH_NONZERO(0x2), BRANCH_ZERO(0x3), - JUMP_ADDRESS(0x4), - ADR(0x5); + BRANCH_BIT_NONZERO(0x4), + BRANCH_BIT_ZERO(0x5), + JUMP_ADDRESS(0x6), + ADR(0x7); /** * Offset by which additional information for branch conditionally, branch zero and branch @@ -1194,6 +1296,46 @@ public class AArch64MacroAssembler extends AArch64Assembler { } } + /** + * Test a single bit and branch if the bit is nonzero. + * + * @param cmp general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. + */ + public void tbnz(Register cmp, int uimm6, Label label) { + assert NumUtil.isUnsignedNbit(6, uimm6); + if (label.isBound()) { + int offset = label.position() - position(); + super.tbnz(cmp, uimm6, offset); + } else { + label.addPatchAt(position()); + int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; + int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); + emitInt(PatchLabelKind.BRANCH_BIT_NONZERO.encoding | indexEncoding | regEncoding); + } + } + + /** + * Test a single bit and branch if the bit is zero. + * + * @param cmp general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. + */ + public void tbz(Register cmp, int uimm6, Label label) { + assert NumUtil.isUnsignedNbit(6, uimm6); + if (label.isBound()) { + int offset = label.position() - position(); + super.tbz(cmp, uimm6, offset); + } else { + label.addPatchAt(position()); + int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; + int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); + emitInt(PatchLabelKind.BRANCH_BIT_ZERO.encoding | indexEncoding | regEncoding); + } + } + /** * Branches to label if condition is true. * @@ -1353,7 +1495,8 @@ public class AArch64MacroAssembler extends AArch64Assembler { super.b(branchOffset, branch); break; case JUMP_ADDRESS: - emitInt(jumpTarget, branch); + int offset = instruction >>> PatchLabelKind.INFORMATION_OFFSET; + emitInt(jumpTarget - offset, branch); break; case BRANCH_NONZERO: case BRANCH_ZERO: { @@ -1373,6 +1516,22 @@ public class AArch64MacroAssembler extends AArch64Assembler { } break; } + case BRANCH_BIT_NONZERO: + case BRANCH_BIT_ZERO: { + int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; + int sizeEncoding = information & NumUtil.getNbitNumberInt(6); + int regEncoding = information >>> 6; + Register reg = AArch64.cpuRegisters.get(regEncoding); + switch (type) { + case BRANCH_BIT_NONZERO: + super.tbnz(reg, sizeEncoding, branchOffset, branch); + break; + case BRANCH_BIT_ZERO: + super.tbz(reg, sizeEncoding, branchOffset, branch); + break; + } + break; + } case ADR: { int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; int regEncoding = information; @@ -1404,4 +1563,14 @@ public class AArch64MacroAssembler extends AArch64Assembler { public AbstractAddress getPlaceholder(int instructionStartPosition) { return AArch64Address.PLACEHOLDER; } + + /** + * Loads an address into Register d. + * + * @param d general purpose register. May not be null. + * @param a AArch64Address the address of an operand. + */ + public void lea(Register d, AArch64Address a) { + a.lea(this, d); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java index a7af5e74a4e..7e7c6cd0245 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java @@ -27,6 +27,16 @@ import static org.junit.Assume.assumeTrue; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import org.graalvm.compiler.asm.amd64.AMD64Assembler; +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.asm.test.AssemblerTest; +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.code.DataSection.Data; +import org.graalvm.compiler.code.DataSection.RawData; +import org.graalvm.compiler.code.DataSection.SerializableData; +import org.junit.Before; +import org.junit.Test; + import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -36,17 +46,6 @@ import jdk.vm.ci.code.site.DataSectionReference; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import org.junit.Before; -import org.junit.Test; - -import org.graalvm.compiler.asm.amd64.AMD64Assembler; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.asm.test.AssemblerTest; -import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.code.DataSection.Data; -import org.graalvm.compiler.code.DataSection.RawData; -import org.graalvm.compiler.code.DataSection.SerializableData; - public class SimpleAssemblerTest extends AssemblerTest { @Before diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java index 1ff59f79536..7b5bec18025 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java @@ -65,6 +65,18 @@ public final class AMD64Address extends AbstractAddress { this(base, Register.None, Scale.Times1, displacement); } + /** + * Creates an {@link AMD64Address} with given base and index registers, scaling and 0 + * displacement. + * + * @param base the base register + * @param index the index register + * @param scale the scaling factor + */ + public AMD64Address(Register base, Register index, Scale scale) { + this(base, index, scale, 0, -1); + } + /** * Creates an {@link AMD64Address} with given base and index registers, scaling and * displacement. This is the most general constructor. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index a69eb78cd50..56090fa7af3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.asm.amd64; -import static org.graalvm.compiler.asm.NumUtil.isByte; -import static org.graalvm.compiler.asm.NumUtil.isInt; -import static org.graalvm.compiler.asm.NumUtil.isShiftCount; -import static org.graalvm.compiler.asm.NumUtil.isUByte; +import static org.graalvm.compiler.core.common.NumUtil.isByte; +import static org.graalvm.compiler.core.common.NumUtil.isInt; +import static org.graalvm.compiler.core.common.NumUtil.isShiftCount; +import static org.graalvm.compiler.core.common.NumUtil.isUByte; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD; @@ -58,7 +58,7 @@ import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import jdk.vm.ci.amd64.AMD64; @@ -2494,6 +2494,24 @@ public class AMD64Assembler extends Assembler { emitByte(0xC0 | encode); } + void pcmpestri(Register dst, AMD64Address src, int imm8) { + assert supports(CPUFeature.SSE4_2); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes); + emitByte(0x61); + emitOperandHelper(dst, src, 0); + emitByte(imm8); + } + + void pcmpestri(Register dst, Register src, int imm8) { + assert supports(CPUFeature.SSE4_2); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes); + emitByte(0x61); + emitByte(0xC0 | encode); + emitByte(imm8); + } + public final void push(Register src) { int encode = prefixAndEncode(src.encoding); emitByte(0x50 | encode); @@ -2633,6 +2651,16 @@ public class AMD64Assembler extends Assembler { emitByte(imm8); } + public final void psrldq(Register dst, int imm8) { + assert isUByte(imm8) : "invalid value"; + assert dst.getRegisterCategory().equals(AMD64.XMM); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + int encode = simdPrefixAndEncode(AMD64.xmm3, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes); + emitByte(0x73); + emitByte(0xC0 | encode); + emitByte(imm8); + } + public final void pshufd(Register dst, Register src, int imm8) { assert isUByte(imm8) : "invalid value"; assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM); @@ -3322,6 +3350,13 @@ public class AMD64Assembler extends Assembler { } } + public final void movdl(Register dst, AMD64Address src) { + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes); + emitByte(0x6E); + emitOperandHelper(dst, src, 0); + } + public final void movddup(Register dst, Register src) { assert supports(CPUFeature.SSE3); assert dst.getRegisterCategory().equals(AMD64.XMM); @@ -3457,6 +3492,14 @@ public class AMD64Assembler extends Assembler { emitByte(0xC0 | encode); } + public final void btrq(Register src, int imm8) { + int encode = prefixqAndEncode(src.encoding); + emitByte(0x0F); + emitByte(0xBA); + emitByte(0xF0 | encode); + emitByte(imm8); + } + public final void xaddl(AMD64Address dst, Register src) { prefix(dst, src); emitByte(0x0F); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java index fc4f7e74edc..36995bf6853 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java @@ -22,11 +22,17 @@ */ package org.graalvm.compiler.asm.amd64; +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.amd64.AMD64.rsp; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -138,6 +144,10 @@ public class AMD64MacroAssembler extends AMD64Assembler { cmpq(src1, src2); } + public final void decrementl(Register reg) { + decrementl(reg, 1); + } + public final void decrementl(Register reg, int value) { if (value == Integer.MIN_VALUE) { subl(reg, value); @@ -321,4 +331,434 @@ public class AMD64MacroAssembler extends AMD64Assembler { movdbl(dest, tmp); addq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes()); } + + // IndexOf for constant substrings with size >= 8 chars + // which don't need to be loaded through stack. + public void stringIndexofC8(Register str1, Register str2, + Register cnt1, Register cnt2, + int intCnt2, Register result, + Register vec, Register tmp) { + // assert(UseSSE42Intrinsics, "SSE4.2 is required"); + + // This method uses pcmpestri inxtruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + + Label reloadSubstr = new Label(); + Label scanToSubstr = new Label(); + Label scanSubstr = new Label(); + Label retFound = new Label(); + Label retNotFound = new Label(); + Label exit = new Label(); + Label foundSubstr = new Label(); + Label matchSubstrHead = new Label(); + Label reloadStr = new Label(); + Label foundCandidate = new Label(); + + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + assert intCnt2 >= 8 : "this code isused only for cnt2 >= 8 chars"; + + // Load substring. + movdqu(vec, new AMD64Address(str2, 0)); + movl(cnt2, intCnt2); + movq(result, str1); // string addr + + if (intCnt2 > 8) { + jmpb(scanToSubstr); + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(reloadSubstr); + movdqu(vec, new AMD64Address(str2, 0)); + negq(cnt2); // Jumped here with negative cnt2, convert to positive + + bind(reloadStr); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + + // cnt2 is number of substring reminding elements and + // cnt1 is number of string reminding elements when cmp failed. + // Restored cnt1 = cnt1 - cnt2 + int_cnt2 + subl(cnt1, cnt2); + addl(cnt1, intCnt2); + movl(cnt2, intCnt2); // Now restore cnt2 + + decrementl(cnt1, 1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + + addq(result, 2); + + } // (int_cnt2 > 8) + + // Scan string for start of substr in 16-byte vectors + bind(scanToSubstr); + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + jccb(ConditionFlag.Below, foundCandidate); // CF == 1 + subl(cnt1, 8); + jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + addq(result, 16); + jmpb(scanToSubstr); + + // Found a potential substr + bind(foundCandidate); + // Matched whole vector if first element matched (tmp(rcx) == 0). + if (intCnt2 == 8) { + jccb(ConditionFlag.Overflow, retFound); // OF == 1 + } else { // int_cnt2 > 8 + jccb(ConditionFlag.Overflow, foundSubstr); + } + // After pcmpestri tmp(rcx) contains matched element index + // Compute start addr of substr + leaq(result, new AMD64Address(result, tmp, Scale.Times2, 0)); + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + if (intCnt2 == 8) { + jccb(ConditionFlag.GreaterEqual, scanToSubstr); + } else { // int_cnt2 > 8 + jccb(ConditionFlag.GreaterEqual, matchSubstrHead); + } + // Left less then substring. + + bind(retNotFound); + movl(result, -1); + jmpb(exit); + + if (intCnt2 > 8) { + // This code is optimized for the case when whole substring + // is matched if its head is matched. + bind(matchSubstrHead); + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + // Reload only string if does not match + jccb(ConditionFlag.NoOverflow, reloadStr); // OF == 0 + + Label contScanSubstr = new Label(); + // Compare the rest of substring (> 8 chars). + bind(foundSubstr); + // First 8 chars are already matched. + negq(cnt2); + addq(cnt2, 8); + + bind(scanSubstr); + subl(cnt1, 8); + cmpl(cnt2, -8); // Do not read beyond substring + jccb(ConditionFlag.LessEqual, contScanSubstr); + // Back-up strings to avoid reading beyond substring: + // cnt1 = cnt1 - cnt2 + 8 + addl(cnt1, cnt2); // cnt2 is negative + addl(cnt1, 8); + movl(cnt2, 8); + negq(cnt2); + bind(contScanSubstr); + if (intCnt2 < 1024 * 1024 * 1024) { + movdqu(vec, new AMD64Address(str2, cnt2, Scale.Times2, intCnt2 * 2)); + pcmpestri(vec, new AMD64Address(result, cnt2, Scale.Times2, intCnt2 * 2), 0x0d); + } else { + // calculate index in register to avoid integer overflow (int_cnt2*2) + movl(tmp, intCnt2); + addq(tmp, cnt2); + movdqu(vec, new AMD64Address(str2, tmp, Scale.Times2, 0)); + pcmpestri(vec, new AMD64Address(result, tmp, Scale.Times2, 0), 0x0d); + } + // Need to reload strings pointers if not matched whole vector + jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0 + addq(cnt2, 8); + jcc(ConditionFlag.Negative, scanSubstr); + // Fall through if found full substring + + } // (int_cnt2 > 8) + + bind(retFound); + // Found result if we matched full small substring. + // Compute substr offset + subq(result, str1); + shrl(result, 1); // index + bind(exit); + + } // string_indexofC8 + + // Small strings are loaded through stack if they cross page boundary. + public void stringIndexOf(Register str1, Register str2, + Register cnt1, Register cnt2, + int intCnt2, Register result, + Register vec, Register tmp, int vmPageSize) { + // + // int_cnt2 is length of small (< 8 chars) constant substring + // or (-1) for non constant substring in which case its length + // is in cnt2 register. + // + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + // + assert intCnt2 == -1 || (0 < intCnt2 && intCnt2 < 8) : "should be != 0"; + + // This method uses pcmpestri instruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + + Label reloadSubstr = new Label(); + Label scanToSubstr = new Label(); + Label scanSubstr = new Label(); + Label adjustStr = new Label(); + Label retFound = new Label(); + Label retNotFound = new Label(); + Label cleanup = new Label(); + Label foundSubstr = new Label(); + Label foundCandidate = new Label(); + + int wordSize = 8; + // We don't know where these strings are located + // and we can't read beyond them. Load them through stack. + Label bigStrings = new Label(); + Label checkStr = new Label(); + Label copySubstr = new Label(); + Label copyStr = new Label(); + + movq(tmp, rsp); // save old SP + + if (intCnt2 > 0) { // small (< 8 chars) constant substring + if (intCnt2 == 1) { // One char + movzwl(result, new AMD64Address(str2, 0)); + movdl(vec, result); // move 32 bits + } else if (intCnt2 == 2) { // Two chars + movdl(vec, new AMD64Address(str2, 0)); // move 32 bits + } else if (intCnt2 == 4) { // Four chars + movq(vec, new AMD64Address(str2, 0)); // move 64 bits + } else { // cnt2 = { 3, 5, 6, 7 } + // Array header size is 12 bytes in 32-bit VM + // + 6 bytes for 3 chars == 18 bytes, + // enough space to load vec and shift. + movdqu(vec, new AMD64Address(str2, (intCnt2 * 2) - 16)); + psrldq(vec, 16 - (intCnt2 * 2)); + } + } else { // not constant substring + cmpl(cnt2, 8); + jccb(ConditionFlag.AboveEqual, bigStrings); // Both strings are big enough + + // We can read beyond string if str+16 does not cross page boundary + // since heaps are aligned and mapped by pages. + assert vmPageSize < 1024 * 1024 * 1024 : "default page should be small"; + movl(result, str2); // We need only low 32 bits + andl(result, (vmPageSize - 1)); + cmpl(result, (vmPageSize - 16)); + jccb(ConditionFlag.BelowEqual, checkStr); + + // Move small strings to stack to allow load 16 bytes into vec. + subq(rsp, 16); + int stackOffset = wordSize - 2; + push(cnt2); + + bind(copySubstr); + movzwl(result, new AMD64Address(str2, cnt2, Scale.Times2, -2)); + movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result); + decrementl(cnt2, 1); + jccb(ConditionFlag.NotZero, copySubstr); + + pop(cnt2); + movq(str2, rsp); // New substring address + } // non constant + + bind(checkStr); + cmpl(cnt1, 8); + jccb(ConditionFlag.AboveEqual, bigStrings); + + // Check cross page boundary. + movl(result, str1); // We need only low 32 bits + andl(result, (vmPageSize - 1)); + cmpl(result, (vmPageSize - 16)); + jccb(ConditionFlag.BelowEqual, bigStrings); + + subq(rsp, 16); + int stackOffset = -2; + if (intCnt2 < 0) { // not constant + push(cnt2); + stackOffset += wordSize; + } + movl(cnt2, cnt1); + + bind(copyStr); + movzwl(result, new AMD64Address(str1, cnt2, Scale.Times2, -2)); + movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result); + decrementl(cnt2, 1); + jccb(ConditionFlag.NotZero, copyStr); + + if (intCnt2 < 0) { // not constant + pop(cnt2); + } + movq(str1, rsp); // New string address + + bind(bigStrings); + // Load substring. + if (intCnt2 < 0) { // -1 + movdqu(vec, new AMD64Address(str2, 0)); + push(cnt2); // substr count + push(str2); // substr addr + push(str1); // string addr + } else { + // Small (< 8 chars) constant substrings are loaded already. + movl(cnt2, intCnt2); + } + push(tmp); // original SP + // Finished loading + + // ======================================================== + // Start search + // + + movq(result, str1); // string addr + + if (intCnt2 < 0) { // Only for non constant substring + jmpb(scanToSubstr); + + // SP saved at sp+0 + // String saved at sp+1*wordSize + // Substr saved at sp+2*wordSize + // Substr count saved at sp+3*wordSize + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(reloadSubstr); + movq(str2, new AMD64Address(rsp, 2 * wordSize)); + movl(cnt2, new AMD64Address(rsp, 3 * wordSize)); + movdqu(vec, new AMD64Address(str2, 0)); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + subq(str1, result); // Restore counter + shrl(str1, 1); + addl(cnt1, str1); + decrementl(cnt1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + + addq(result, 2); + } // non constant + + // Scan string for start of substr in 16-byte vectors + bind(scanToSubstr); + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + jccb(ConditionFlag.Below, foundCandidate); // CF == 1 + subl(cnt1, 8); + jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + addq(result, 16); + + bind(adjustStr); + cmpl(cnt1, 8); // Do not read beyond string + jccb(ConditionFlag.GreaterEqual, scanToSubstr); + // Back-up string to avoid reading beyond string. + leaq(result, new AMD64Address(result, cnt1, Scale.Times2, -16)); + movl(cnt1, 8); + jmpb(scanToSubstr); + + // Found a potential substr + bind(foundCandidate); + // After pcmpestri tmp(rcx) contains matched element index + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + jccb(ConditionFlag.GreaterEqual, foundSubstr); + // Left less then substring. + + bind(retNotFound); + movl(result, -1); + jmpb(cleanup); + + bind(foundSubstr); + // Compute start addr of substr + leaq(result, new AMD64Address(result, tmp, Scale.Times2)); + + if (intCnt2 > 0) { // Constant substring + // Repeat search for small substring (< 8 chars) + // from new point without reloading substring. + // Have to check that we don't read beyond string. + cmpl(tmp, 8 - intCnt2); + jccb(ConditionFlag.Greater, adjustStr); + // Fall through if matched whole substring. + } else { // non constant + assert intCnt2 == -1 : "should be != 0"; + + addl(tmp, cnt2); + // Found result if we matched whole substring. + cmpl(tmp, 8); + jccb(ConditionFlag.LessEqual, retFound); + + // Repeat search for small substring (<= 8 chars) + // from new point 'str1' without reloading substring. + cmpl(cnt2, 8); + // Have to check that we don't read beyond string. + jccb(ConditionFlag.LessEqual, adjustStr); + + Label checkNext = new Label(); + Label contScanSubstr = new Label(); + Label retFoundLong = new Label(); + // Compare the rest of substring (> 8 chars). + movq(str1, result); + + cmpl(tmp, cnt2); + // First 8 chars are already matched. + jccb(ConditionFlag.Equal, checkNext); + + bind(scanSubstr); + pcmpestri(vec, new AMD64Address(str1, 0), 0x0d); + // Need to reload strings pointers if not matched whole vector + jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0 + + bind(checkNext); + subl(cnt2, 8); + jccb(ConditionFlag.LessEqual, retFoundLong); // Found full substring + addq(str1, 16); + addq(str2, 16); + subl(cnt1, 8); + cmpl(cnt2, 8); // Do not read beyond substring + jccb(ConditionFlag.GreaterEqual, contScanSubstr); + // Back-up strings to avoid reading beyond substring. + leaq(str2, new AMD64Address(str2, cnt2, Scale.Times2, -16)); + leaq(str1, new AMD64Address(str1, cnt2, Scale.Times2, -16)); + subl(cnt1, cnt2); + movl(cnt2, 8); + addl(cnt1, 8); + bind(contScanSubstr); + movdqu(vec, new AMD64Address(str2, 0)); + jmpb(scanSubstr); + + bind(retFoundLong); + movq(str1, new AMD64Address(rsp, wordSize)); + } // non constant + + bind(retFound); + // Compute substr offset + subq(result, str1); + shrl(result, 1); // index + + bind(cleanup); + pop(rsp); // restore SP + + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java index 68cde9dcfdf..582247c4d72 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -135,8 +135,8 @@ import java.util.Map; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.Register; @@ -1757,6 +1757,10 @@ public abstract class SPARCAssembler extends Assembler { return constant.isNull() || isSimm(constant.asLong(), 5); } + public static boolean isSimm5(long imm) { + return isSimm(imm, 5); + } + public static boolean isSimm13(int imm) { return isSimm(imm, 13); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java index 47615118361..59ef7ff2c16 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java @@ -81,6 +81,10 @@ public class SPARCMacroAssembler extends SPARCAssembler { nop(); // delay slot } + public void bz(Label l) { + BPCC.emit(this, Xcc, ConditionFlag.Zero, NOT_ANNUL, PREDICT_NOT_TAKEN, l); + } + @Override protected final void patchJumpTarget(int branch, int branchTarget) { final int disp = (branchTarget - branch) / 4; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java index a7c1fb03087..ae3f80e723a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java @@ -26,8 +26,6 @@ import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCo import java.lang.reflect.Method; -import org.junit.Assert; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.DisassemblerProvider; @@ -36,10 +34,11 @@ import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.test.GraalTest; +import org.junit.Assert; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CodeCacheProvider; @@ -62,6 +61,14 @@ public abstract class AssemblerTest extends GraalTest { byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc); } + /** + * Gets the initial option values provided by the Graal runtime. These are option values + * typically parsed from the command line. + */ + public static OptionValues getInitialOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + public AssemblerTest() { JVMCIBackend providers = JVMCI.getRuntime().getHostJVMCIBackend(); this.metaAccess = providers.getMetaAccess(); @@ -79,7 +86,8 @@ public abstract class AssemblerTest extends GraalTest { try (Scope s = Debug.scope("assembleMethod", method, codeCache)) { RegisterConfig registerConfig = codeCache.getRegisterConfig(); CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); - CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, new StructuredGraph(method, AllowAssumptions.NO, compilationId), null).getCallingConvention(); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).compilationId(compilationId).build(); + CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention(); CompilationResult compResult = new CompilationResult(); byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java index d6df78393ea..4d8c3ea1cbb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.asm; +import org.graalvm.compiler.core.common.NumUtil; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java index 60f0b5203d1..59b791bdb4e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java @@ -63,6 +63,11 @@ public interface Bytecode { ExceptionHandler[] getExceptionHandlers(); + /** + * Gets the {@link BytecodeProvider} from which this object was acquired. + */ + BytecodeProvider getOrigin(); + static String toLocation(Bytecode bytecode, int bci) { return appendLocation(new StringBuilder(), bytecode, bci).toString(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java index 39b6e83f65b..ee9c81278f7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java @@ -36,9 +36,20 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ResolvedJavaMethodBytecode implements Bytecode { private final ResolvedJavaMethod method; + private final BytecodeProvider origin; public ResolvedJavaMethodBytecode(ResolvedJavaMethod method) { + this(method, ResolvedJavaMethodBytecodeProvider.INSTANCE); + } + + public ResolvedJavaMethodBytecode(ResolvedJavaMethod method, BytecodeProvider origin) { this.method = method; + this.origin = origin; + } + + @Override + public BytecodeProvider getOrigin() { + return origin; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java index b2f0409a3ba..a4b3149bac5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java @@ -29,9 +29,14 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class ResolvedJavaMethodBytecodeProvider implements BytecodeProvider { + /** + * A state-less, shared {@link ResolvedJavaMethodBytecodeProvider} instance. + */ + public static final ResolvedJavaMethodBytecodeProvider INSTANCE = new ResolvedJavaMethodBytecodeProvider(); + @Override public Bytecode getBytecode(ResolvedJavaMethod method) { - return new ResolvedJavaMethodBytecode(method); + return new ResolvedJavaMethodBytecode(method, this); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java index ba1267bca4b..4c7bfafaff9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Objects; import org.graalvm.compiler.graph.NodeSourcePosition; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.StackSlot; @@ -299,7 +300,6 @@ public class CompilationResult { * Sets the assumptions made during compilation. */ public void setAssumptions(Assumption[] assumptions) { - checkOpen(); this.assumptions = assumptions; } @@ -363,9 +363,10 @@ public class CompilationResult { * * @param accessedFields the collected set of fields accessed during compilation */ - public void setFields(Collection accessedFields) { - assert accessedFields != null; - fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]); + public void setFields(EconomicSet accessedFields) { + if (accessedFields != null) { + fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]); + } } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java index d28ab09afd2..96570b3cb09 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.code; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; /** * Represents a bailout exception with a stack trace in terms of the Java source being compiled diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java new file mode 100644 index 00000000000..f584d35d65a --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015, 2016, 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 jdk.vm.ci.meta.JavaConstant; +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.AddNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.memory.address.RawAddressNode; +import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase; + +public class AArch64AddressLoweringByUse extends AddressLoweringByUsePhase.AddressLoweringByUse { + private AArch64LIRKindTool kindtool; + + public AArch64AddressLoweringByUse(AArch64LIRKindTool kindtool) { + this.kindtool = kindtool; + } + + @Override + public AddressNode lower(ValueNode use, Stamp stamp, AddressNode address) { + if (address instanceof RawAddressNode) { + return doLower(stamp, address.getBase(), null); + } else if (address instanceof OffsetAddressNode) { + OffsetAddressNode offsetAddress = (OffsetAddressNode) address; + return doLower(stamp, offsetAddress.getBase(), offsetAddress.getOffset()); + } else { + // must be an already transformed AArch64AddressNode + return address; + } + } + + @Override + public AddressNode lower(AddressNode address) { + return lower(null, null, address); + } + + private AddressNode doLower(Stamp stamp, ValueNode base, ValueNode index) { + AArch64AddressNode ret = new AArch64AddressNode(base, index); + AArch64Kind aarch64Kind = (stamp == null ? null : getAArch64Kind(stamp)); + + // improve the address as much as possible + boolean changed; + do { + changed = improve(aarch64Kind, ret); + } while (changed); + + // avoid duplicates + return base.graph().unique(ret); + } + + protected boolean improve(AArch64Kind kind, AArch64AddressNode ret) { + AArch64Address.AddressingMode mode = ret.getAddressingMode(); + // if we have already set a displacement or set to base only mode then we are done + if (isDisplacementMode(mode) || isBaseOnlyMode(mode)) { + return false; + } + ValueNode base = ret.getBase(); + ValueNode index = ret.getIndex(); + + // avoid a constant or null base if possible + if (base == null) { + ret.setBase(index); + ret.setIndex(base); + return true; + } + // make sure any integral JavaConstant + // is the index rather than the base + // strictly we don't need the conditions on index + // as we ought not to see two JavaConstant values + if (base.isJavaConstant() && base.asJavaConstant().getJavaKind().isNumericInteger() && + index != null && !index.isJavaConstant()) { + ret.setBase(index); + ret.setIndex(base); + return true; + } + + // if the base is an add then move it up + if (index == null && base instanceof AddNode) { + AddNode add = (AddNode) base; + ret.setBase(add.getX()); + ret.setIndex(add.getY()); + return true; + } + + // we can try to fold a JavaConstant index into a displacement + if (index != null && index.isJavaConstant()) { + JavaConstant javaConstant = index.asJavaConstant(); + if (javaConstant.getJavaKind().isNumericInteger()) { + long disp = javaConstant.asLong(); + mode = immediateMode(kind, disp); + if (isDisplacementMode(mode)) { + index = null; + // we can fold this in as a displacement + // but first see if we can pull up any additional + // constants added into the base + boolean tryNextBase = (base instanceof AddNode); + while (tryNextBase) { + AddNode add = (AddNode) base; + tryNextBase = false; + ValueNode child = add.getX(); + if (child.isJavaConstant() && child.asJavaConstant().getJavaKind().isNumericInteger()) { + long newDisp = disp + child.asJavaConstant().asLong(); + AArch64Address.AddressingMode newMode = immediateMode(kind, newDisp); + if (newMode != AArch64Address.AddressingMode.REGISTER_OFFSET) { + disp = newDisp; + mode = newMode; + base = add.getY(); + ret.setBase(base); + tryNextBase = (base instanceof AddNode); + } + } else { + child = add.getY(); + if (child.isJavaConstant() && child.asJavaConstant().getJavaKind().isNumericInteger()) { + long newDisp = disp + child.asJavaConstant().asLong(); + AArch64Address.AddressingMode newMode = immediateMode(kind, newDisp); + if (newMode != AArch64Address.AddressingMode.REGISTER_OFFSET) { + disp = newDisp; + mode = newMode; + base = add.getX(); + ret.setBase(base); + tryNextBase = (base instanceof AddNode); + } + } + } + } + if (disp != 0) { + // ok now set the displacement in place of an index + ret.setIndex(null); + int scaleFactor = computeScaleFactor(kind, mode); + ret.setDisplacement(disp, scaleFactor, mode); + } else { + // reset to base register only + ret.setIndex(null); + ret.setDisplacement(0, 1, AArch64Address.AddressingMode.BASE_REGISTER_ONLY); + } + return true; + } + } + } + // nope cannot improve this any more + return false; + } + + private AArch64Kind getAArch64Kind(Stamp stamp) { + LIRKind lirKind = stamp.getLIRKind(kindtool); + if (!lirKind.isValue()) { + if (!lirKind.isReference(0) || lirKind.getReferenceCount() != 1) { + return null; + } + } + + return (AArch64Kind) lirKind.getPlatformKind(); + } + + private static AArch64Address.AddressingMode immediateMode(AArch64Kind kind, long value) { + if (kind != null) { + int size = kind.getSizeInBytes(); + // this next test should never really fail + if ((value & (size - 1)) == 0) { + long encodedValue = value / size; + // assert value % size == 0 + // we can try for a 12 bit scaled offset + if (NumUtil.isUnsignedNbit(12, encodedValue)) { + return AArch64Address.AddressingMode.IMMEDIATE_SCALED; + } + } + } + + // we can try for a 9 bit unscaled offset + if (NumUtil.isSignedNbit(9, value)) { + return AArch64Address.AddressingMode.IMMEDIATE_UNSCALED; + } + + // nope this index needs to be passed via offset register + return AArch64Address.AddressingMode.REGISTER_OFFSET; + } + + private static int computeScaleFactor(AArch64Kind kind, AArch64Address.AddressingMode mode) { + if (mode == AArch64Address.AddressingMode.IMMEDIATE_SCALED) { + return kind.getSizeInBytes(); + } + return 1; + } + + boolean isBaseOnlyMode(AArch64Address.AddressingMode addressingMode) { + return addressingMode == AArch64Address.AddressingMode.BASE_REGISTER_ONLY; + } + + private static boolean isDisplacementMode(AArch64Address.AddressingMode addressingMode) { + switch (addressingMode) { + case IMMEDIATE_POST_INDEXED: + case IMMEDIATE_PRE_INDEXED: + case IMMEDIATE_SCALED: + case IMMEDIATE_UNSCALED: + return true; + } + return false; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java index 176480dd2a5..3fddb853424 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java @@ -26,7 +26,6 @@ package org.graalvm.compiler.core.aarch64; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -40,7 +39,7 @@ import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Value; /** - * Represents an address of the form... TODO. + * Represents an AArch64 address in the graph. */ @NodeInfo public class AArch64AddressNode extends AddressNode implements LIRLowerable { @@ -52,7 +51,8 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { @OptionalInput private ValueNode index; private AArch64Address.AddressingMode addressingMode; - private int displacement; + private long displacement; + private int scaleFactor; public AArch64AddressNode(ValueNode base) { this(base, null); @@ -63,6 +63,8 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { this.base = base; this.index = index; this.addressingMode = AddressingMode.REGISTER_OFFSET; + this.displacement = 0; + this.scaleFactor = 1; } @Override @@ -74,9 +76,10 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); AllocatableValue indexReference; - if (addressingMode.equals(AddressingMode.IMMEDIATE_UNSCALED)) { + if (index == null) { + indexReference = null; + } else if (addressingMode.equals(AddressingMode.IMMEDIATE_UNSCALED)) { indexReference = LIRKind.derivedBaseFromValue(indexValue); - throw GraalError.unimplemented(); } else { if (LIRKind.isValue(indexValue.getValueKind())) { indexReference = null; @@ -86,10 +89,10 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { } LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference); - final boolean scaled = false; - gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, displacement, scaled, addressingMode)); + gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, (int) displacement, scaleFactor, addressingMode)); } + @Override public ValueNode getBase() { return base; } @@ -102,6 +105,7 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -114,11 +118,22 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { this.index = index; } - public int getDisplacement() { + public long getDisplacement() { return displacement; } - public void setDisplacement(int displacement) { + public void setDisplacement(long displacement, int scaleFactor, AArch64Address.AddressingMode addressingMode) { this.displacement = displacement; + this.scaleFactor = scaleFactor; + this.addressingMode = addressingMode; + } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } + + public AddressingMode getAddressingMode() { + return addressingMode; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java index 786b6692aa6..aee507d5e24 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java @@ -23,13 +23,16 @@ package org.graalvm.compiler.core.aarch64; -import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; -import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.aarch64.AArch64.sp; import static jdk.vm.ci.aarch64.AArch64Kind.DWORD; import static jdk.vm.ci.aarch64.AArch64Kind.QWORD; +import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.FloatConvert; @@ -41,12 +44,12 @@ import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp; -import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode; import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp; import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp; +import org.graalvm.compiler.lir.aarch64.AArch64Unary; import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; import jdk.vm.ci.aarch64.AArch64Kind; @@ -91,11 +94,30 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } } + protected Value emitExtendMemory(boolean isSigned, AArch64Kind memoryKind, int resultBits, AArch64AddressValue address, LIRFrameState state) { + // Issue a zero extending load of the proper bit size and set the result to + // the proper kind. + Variable result = getLIRGen().newVariable(LIRKind.value(resultBits == 32 ? AArch64Kind.DWORD : AArch64Kind.QWORD)); + + int targetSize = resultBits <= 32 ? 32 : 64; + switch (memoryKind) { + case BYTE: + case WORD: + case DWORD: + case QWORD: + getLIRGen().append(new AArch64Unary.MemoryOp(isSigned, targetSize, + memoryKind.getSizeInBytes() * 8, result, address, state)); + break; + default: + throw GraalError.shouldNotReachHere(); + } + return result; + } + @Override public Value emitMul(Value a, Value b, boolean setFlags) { - // TODO (das) setFlags handling - should be handled higher up. Ask for ideas at mailing list - assert !setFlags : "Set flags on multiplication is not supported"; - return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.MUL, AArch64ArithmeticOp.FMUL), true, a, b); + AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL; + return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b); } @Override @@ -223,7 +245,7 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem @Override public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { - assert fromBits <= toBits && (toBits == 32 || toBits == 64); + assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { return inputVal; } @@ -235,11 +257,21 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem @Override public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { - assert fromBits <= toBits && (toBits == 32 || toBits == 64); + LIRKind resultKind = getResultLirKind(toBits, inputVal); + assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { return inputVal; + } else if (isJavaConstant(inputVal)) { + JavaConstant javaConstant = asJavaConstant(inputVal); + long constant; + if (javaConstant.isNull()) { + constant = 0; + } else { + constant = javaConstant.asLong(); + } + int shiftCount = QWORD.getSizeInBytes() * 8 - fromBits; + return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount)); } - LIRKind resultKind = getResultLirKind(toBits, inputVal); Variable result = getLIRGen().newVariable(resultKind); getLIRGen().append(new AArch64SignExtendOp(result, getLIRGen().asAllocatable(inputVal), fromBits, toBits)); return result; @@ -249,7 +281,8 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem if (resultBitSize == 64) { return LIRKind.combine(inputValues).changeType(QWORD); } else { - assert resultBitSize == 32; + // FIXME: I have no idea what this assert was ever for + // assert resultBitSize == 32; return LIRKind.combine(inputValues).changeType(DWORD); } } @@ -352,8 +385,8 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } @Override - public Value emitBitScanForward(Value inputVal) { - return emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode.BSF, inputVal); + public Variable emitBitScanForward(Value value) { + throw GraalError.unimplemented(); } @Override @@ -362,27 +395,23 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } @Override - public Value emitBitScanReverse(Value inputVal) { - // TODO (das) old implementation said to use emitCountLeadingZeros instead - need extra node - // for that though - return emitBitManipulation(BitManipulationOpCode.BSR, inputVal); + public Value emitBitScanReverse(Value value) { + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(BSR, result, getLIRGen().asAllocatable(value))); + return result; } @Override public Value emitCountLeadingZeros(Value value) { - return emitBitManipulation(BitManipulationOpCode.CLZ, value); + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, getLIRGen().asAllocatable(value))); + return result; } @Override public Value emitCountTrailingZeros(Value value) { - throw GraalError.unimplemented(); - } - - private Variable emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode op, Value inputVal) { - assert isNumericInteger(inputVal.getPlatformKind()); - AllocatableValue input = getLIRGen().asAllocatable(inputVal); - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(new AArch64BitManipulationOp(op, result, input)); + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, getLIRGen().asAllocatable(value))); return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java index 03e777a2aa8..34a7a0872ea 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java @@ -42,11 +42,14 @@ import org.graalvm.compiler.lir.SwitchStrategy; 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.AArch64ArrayEqualsOp; +import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp; import org.graalvm.compiler.lir.aarch64.AArch64Compare; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp; 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.AArch64Move.MembarOp; @@ -56,6 +59,7 @@ import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaConstant; @@ -116,13 +120,24 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { if (address instanceof AArch64AddressValue) { return (AArch64AddressValue) address; } else { - return new AArch64AddressValue(address.getValueKind(), asAllocatable(address), Value.ILLEGAL, 0, false, AddressingMode.BASE_REGISTER_ONLY); + return new AArch64AddressValue(address.getValueKind(), asAllocatable(address), Value.ILLEGAL, 0, 1, AddressingMode.BASE_REGISTER_ONLY); } } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + Variable prevValue = newVariable(expectedValue.getValueKind()); + Variable scratch = newVariable(LIRKind.value(AArch64Kind.DWORD)); + append(new CompareAndSwapOp(prevValue, loadReg(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); + assert trueValue.getValueKind().equals(falseValue.getValueKind()); Variable result = newVariable(trueValue.getValueKind()); + append(new CondMoveOp(result, ConditionFlag.EQ, asAllocatable(trueValue), asAllocatable(falseValue))); + return result; + } + + @Override + public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + Variable result = newVariable(newValue.getValueKind()); Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); append(new CompareAndSwapOp(result, loadNonCompareConst(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); return result; @@ -271,13 +286,25 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { boolean mirrored; AArch64Kind kind = (AArch64Kind) cmpKind; if (kind.isInteger()) { - if (LIRValueUtil.isVariable(b)) { - left = load(b); - right = loadNonConst(a); + Value aExt = a; + Value bExt = b; + + int compareBytes = cmpKind.getSizeInBytes(); + // AArch64 compares 32 or 64 bits: sign extend a and b as required. + if (compareBytes < a.getPlatformKind().getSizeInBytes()) { + aExt = arithmeticLIRGen.emitSignExtend(a, compareBytes * 8, 64); + } + if (compareBytes < b.getPlatformKind().getSizeInBytes()) { + bExt = arithmeticLIRGen.emitSignExtend(b, compareBytes * 8, 64); + } + + if (LIRValueUtil.isVariable(bExt)) { + left = load(bExt); + right = loadNonConst(aExt); mirrored = true; } else { - left = load(a); - right = loadNonConst(b); + left = load(aExt); + right = loadNonConst(bExt); mirrored = false; } append(new AArch64Compare.CompareOp(left, loadNonCompareConst(right))); @@ -367,7 +394,7 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { assert ((AArch64Kind) left.getPlatformKind()).isInteger() && ((AArch64Kind) right.getPlatformKind()).isInteger(); assert ((AArch64Kind) trueValue.getPlatformKind()).isInteger() && ((AArch64Kind) falseValue.getPlatformKind()).isInteger(); - ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(trueValue.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right); + ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(left.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right); Variable result = newVariable(trueValue.getValueKind()); append(new CondMoveOp(result, ConditionFlag.EQ, load(trueValue), load(falseValue))); return result; @@ -385,22 +412,21 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { @Override protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { - // Make copy of key since the TableSwitch destroys its input. - Variable tmp = emitMove(key); - Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); - append(new AArch64ControlFlow.TableSwitchOp(lowKey, defaultTarget, targets, tmp, scratch)); + append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind()))); } @Override - public Variable emitByteSwap(Value operand) { - // TODO (das) Do not generate until we support vector instructions - throw GraalError.unimplemented("Do not generate until we support vector instructions"); + public Variable emitByteSwap(Value input) { + Variable result = newVariable(LIRKind.combine(input)); + append(new AArch64ByteSwapOp(result, input)); + return result; } @Override public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) { - // TODO (das) Do not generate until we support vector instructions - throw GraalError.unimplemented("Do not generate until we support vector instructions"); + Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); + append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length))); + return result; } @Override @@ -443,4 +469,6 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { public void emitPause() { append(new AArch64PauseOp()); } + + public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java index 101a59d96a8..71f55db33c5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java @@ -66,4 +66,13 @@ public class AArch64LIRKindTool implements LIRKindTool { return LIRKind.value(AArch64Kind.QWORD); } + @Override + public LIRKind getNarrowOopKind() { + return LIRKind.reference(AArch64Kind.DWORD); + } + + @Override + public LIRKind getNarrowPointerKind() { + return LIRKind.value(AArch64Kind.DWORD); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java index fe042027b37..0a4a962f4d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java @@ -86,21 +86,25 @@ public class AArch64MoveFactory implements MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - return AArch64MacroAssembler.isMovableImmediate(c.asInt()); - case Long: - return AArch64MacroAssembler.isMovableImmediate(c.asLong()); - case Object: - return c.isNull(); - default: - return false; + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + return AArch64MacroAssembler.isMovableImmediate(c.asInt()); + case Long: + return AArch64MacroAssembler.isMovableImmediate(c.asLong()); + case Object: + return c.isNull(); + default: + return false; + } } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java index b99cd62bdad..1343565bc71 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java @@ -24,9 +24,14 @@ package org.graalvm.compiler.core.aarch64; import org.graalvm.compiler.core.gen.NodeMatchRules; +import org.graalvm.compiler.core.match.ComplexMatchResult; +import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.calc.SignExtendNode; +import org.graalvm.compiler.nodes.calc.ZeroExtendNode; import org.graalvm.compiler.nodes.memory.Access; import jdk.vm.ci.aarch64.AArch64Kind; @@ -56,4 +61,18 @@ public class AArch64NodeMatchRules extends NodeMatchRules { protected AArch64ArithmeticLIRGenerator getArithmeticLIRGenerator() { return (AArch64ArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic(); } + + @MatchRule("(ZeroExtend Read=access)") + @MatchRule("(ZeroExtend FloatingRead=access)") + public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) { + AArch64Kind memoryKind = getMemoryKind(access); + return builder -> getArithmeticLIRGenerator().emitExtendMemory(false, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access)); + } + + @MatchRule("(SignExtend Read=access)") + @MatchRule("(SignExtend FloatingRead=access)") + public ComplexMatchResult signExtend(SignExtendNode root, Access access) { + AArch64Kind memoryKind = getMemoryKind(access); + return builder -> getArithmeticLIRGenerator().emitExtendMemory(true, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access)); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java similarity index 85% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java index 4eadf9cfaa3..e8b9b02bb7a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.core.aarch64; -import org.graalvm.compiler.java.DefaultSuitesProvider; +import org.graalvm.compiler.java.DefaultSuitesCreator; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -public class AArch64SuitesProvider extends DefaultSuitesProvider { +public class AArch64SuitesCreator extends DefaultSuitesCreator { - public AArch64SuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java index 0904f9ce409..c95707da994 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java @@ -38,8 +38,8 @@ public class AMD64AllocatorTest extends AllocatorTest { @Before public void checkAMD64() { assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64); - assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue() == null); - assumeTrue("TraceRA is set -> skip", !TraceRA.getValue()); + assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); + assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java index a1384c11e43..7a6c0505481 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java @@ -24,22 +24,23 @@ package org.graalvm.compiler.core.amd64.test; import static org.junit.Assume.assumeTrue; -import org.junit.Before; -import org.junit.Test; - import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.MemoryConstOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.jtt.LIRTest; import org.graalvm.compiler.lir.phases.LIRPhase; +import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.TargetDescription; public class MatchRuleTest extends LIRTest { - private static LIR lir; + private LIR lir; @Before public void checkAMD64() { @@ -54,13 +55,19 @@ public class MatchRuleTest extends LIRTest { } } + @Override + protected LIRSuites createLIRSuites(OptionValues options) { + LIRSuites suites = super.createLIRSuites(options); + suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); + return suites; + } + /** * Verifies, if the match rules in AMD64NodeMatchRules do work on the graphs by compiling and * checking if the expected LIR instruction show up. */ @Test public void test1() { - getLIRSuites().getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); compile(getResolvedJavaMethod("test1Snippet"), null); boolean found = false; for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { @@ -83,7 +90,7 @@ public class MatchRuleTest extends LIRTest { } } - public static class CheckPhase extends LIRPhase { + public class CheckPhase extends LIRPhase { @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) { lir = lirGenRes.getLIR(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java index a43d03467b1..567a826055f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.core.amd64; import jdk.vm.ci.meta.JavaConstant; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.common.type.IntegerStamp; import org.graalvm.compiler.nodes.ValueNode; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java index 1281418aece..a3c7b5da3e1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java @@ -73,7 +73,9 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); AllocatableValue indexReference; - if (scale.equals(Scale.Times1)) { + if (index == null) { + indexReference = null; + } else if (scale.equals(Scale.Times1)) { indexReference = LIRKind.derivedBaseFromValue(indexValue); } else { if (LIRKind.isValue(indexValue)) { @@ -87,6 +89,7 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { gen.setResult(this, new AMD64AddressValue(kind, baseValue, indexValue, scale, displacement)); } + @Override public ValueNode getBase() { return base; } @@ -99,6 +102,7 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -126,4 +130,9 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { public void setDisplacement(int displacement) { this.displacement = displacement; } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index 4eba24888a6..0971cf54b71 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -74,7 +74,7 @@ import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntr import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP; import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; @@ -1234,7 +1234,7 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen return; } else if (c instanceof VMConstant) { VMConstant vc = (VMConstant) c; - if (size == DWORD && !GeneratePIC.getValue()) { + if (size == DWORD && !GeneratePIC.getValue(getOptions())) { getLIRGen().append(new AMD64BinaryConsumer.VMConstOp(CMP.getMIOpcode(DWORD, false), left, vc)); } else { getLIRGen().append(new AMD64BinaryConsumer.DataOp(CMP.getRMOpcode(size), size, left, vc)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java index f9d2f5c8e62..e207f830464 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.core.amd64; +import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD; @@ -31,10 +32,10 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; -import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; @@ -72,6 +73,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp; import org.graalvm.compiler.lir.amd64.AMD64Move.StackLeaOp; import org.graalvm.compiler.lir.amd64.AMD64PauseOp; +import org.graalvm.compiler.lir.amd64.AMD64StringIndexOfOp; import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp; import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -112,10 +114,8 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { protected static final boolean canStoreConstant(JavaConstant c) { // there is no immediate move of 64-bit constants on Intel switch (c.getJavaKind()) { - case Long: { - long l = c.asLong(); - return (int) l == l; - } + case Long: + return NumUtil.isInt(c.asLong()); case Double: return false; case Object: @@ -183,7 +183,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); @@ -199,6 +199,33 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { return result; } + @Override + public Value emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + ValueKind kind = newValue.getValueKind(); + assert kind.equals(expectedValue.getValueKind()); + AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); + + AMD64AddressValue addressValue = asAddressValue(address); + RegisterValue raxRes = AMD64.rax.asValue(kind); + emitMove(raxRes, expectedValue); + append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue))); + Variable result = newVariable(kind); + emitMove(result, raxRes); + return result; + } + + public void emitCompareAndSwapBranch(ValueKind kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel, + double trueLabelProbability) { + assert kind.equals(expectedValue.getValueKind()); + assert kind.equals(newValue.getValueKind()); + assert condition == Condition.EQ || condition == Condition.NE; + AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); + RegisterValue raxValue = AMD64.rax.asValue(kind); + emitMove(raxValue, expectedValue); + append(new CompareAndSwapOp(memKind, raxValue, address, raxValue, asAllocatable(newValue))); + append(new BranchOp(condition, trueLabel, falseLabel, trueLabelProbability)); + } + @Override public Value emitAtomicReadAndAdd(Value address, Value delta) { ValueKind kind = delta.getValueKind(); @@ -329,7 +356,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { throw GraalError.shouldNotReachHere("unexpected kind: " + cmpKind); } - if (isJavaConstant(a)) { + if (isConstantValue(a)) { return emitCompareMemoryConOp(size, asConstantValue(a), b, state); } else { return emitCompareRegMemoryOp(size, asAllocatable(a), b, state); @@ -399,7 +426,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { @Override protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { long maxOffset = linkage.getMaxCallTargetOffset(); - if (maxOffset != (int) maxOffset && !GeneratePIC.getValue()) { + if (maxOffset != (int) maxOffset && !GeneratePIC.getValue(getResult().getLIR().getOptions())) { append(new AMD64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info)); } else { append(new AMD64Call.DirectNearForeignCallOp(linkage, result, arguments, temps, info)); @@ -420,6 +447,24 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { return result; } + /** + * Return a conservative estimate of the page size for use by the String.indexOf intrinsic. + */ + protected int getVMPageSize() { + return 4096; + } + + @Override + public Variable emitStringIndexOf(Value source, Value sourceCount, Value target, Value targetCount, int constantTargetCount) { + Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); + RegisterValue cnt1 = AMD64.rdx.asValue(sourceCount.getValueKind()); + emitMove(cnt1, sourceCount); + RegisterValue cnt2 = AMD64.rax.asValue(targetCount.getValueKind()); + emitMove(cnt2, targetCount); + append(new AMD64StringIndexOfOp(this, result, source, target, cnt1, cnt2, AMD64.rcx.asValue(), AMD64.xmm0.asValue(), constantTargetCount, getVMPageSize())); + return result; + } + @Override public void emitReturn(JavaKind kind, Value input) { AllocatableValue operand = Value.ILLEGAL; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java index 7a0ad5bfc24..a2ff74c5f66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java @@ -66,4 +66,13 @@ public class AMD64LIRKindTool implements LIRKindTool { return LIRKind.value(AMD64Kind.QWORD); } + @Override + public LIRKind getNarrowOopKind() { + return LIRKind.reference(AMD64Kind.DWORD); + } + + @Override + public LIRKind getNarrowPointerKind() { + return LIRKind.value(AMD64Kind.DWORD); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java index fb767ee07fe..23904826487 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java @@ -28,7 +28,7 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; import static jdk.vm.ci.code.ValueUtil.isRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.DataPointerConstant; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; @@ -54,15 +54,19 @@ public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Long: - return NumUtil.isInt(c.asLong()); - case Object: - return c.isNull(); - default: - return true; + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Long: + return NumUtil.isInt(c.asLong()); + case Object: + return c.isNull(); + default: + return true; + } } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java index 2ff74388f70..198998ae652 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java @@ -26,15 +26,14 @@ package org.graalvm.compiler.core.amd64; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD; -import java.util.HashMap; -import java.util.Map; - import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64PushPopStackMove; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Architecture; @@ -61,7 +60,7 @@ public abstract class AMD64MoveFactoryBase implements MoveFactory { public static final class BackupSlotProvider { private final FrameMapBuilder frameMapBuilder; - private Map categorized; + private EconomicMap categorized; public BackupSlotProvider(FrameMapBuilder frameMapBuilder) { this.frameMapBuilder = frameMapBuilder; @@ -70,7 +69,7 @@ public abstract class AMD64MoveFactoryBase implements MoveFactory { protected RegisterBackupPair getScratchRegister(PlatformKind kind) { PlatformKind.Key key = kind.getKey(); if (categorized == null) { - categorized = new HashMap<>(); + categorized = EconomicMap.create(Equivalence.DEFAULT); } else if (categorized.containsKey(key)) { return categorized.get(key); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java index 7787dd0e565..77355d4ab41 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java @@ -36,13 +36,13 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp; +import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp; -import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeLIRBuilder; @@ -52,6 +52,7 @@ import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRValueUtil; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer; @@ -69,18 +70,22 @@ import org.graalvm.compiler.nodes.calc.ReinterpretNode; import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.Access; +import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.util.GraphUtil; import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.amd64.AMD64.CPUFeature; +import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.PlatformKind; import jdk.vm.ci.meta.Value; +import jdk.vm.ci.meta.ValueKind; public class AMD64NodeMatchRules extends NodeMatchRules { @@ -95,11 +100,15 @@ public class AMD64NodeMatchRules extends NodeMatchRules { return null; } - protected AMD64Kind getMemoryKind(Access access) { - return (AMD64Kind) gen.getLIRKind(access.asNode().stamp()).getPlatformKind(); + protected AMD64Kind getMemoryKind(LIRLowerableAccess access) { + return (AMD64Kind) getLirKind(access).getPlatformKind(); } - protected OperandSize getMemorySize(Access access) { + protected LIRKind getLirKind(LIRLowerableAccess access) { + return gen.getLIRKind(access.getAccessStamp()); + } + + protected OperandSize getMemorySize(LIRLowerableAccess access) { switch (getMemoryKind(access)) { case BYTE: return OperandSize.BYTE; @@ -118,25 +127,36 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } - protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, Access access) { + protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, LIRLowerableAccess access) { Condition cond = compare.condition(); AMD64Kind kind = getMemoryKind(access); + boolean matchedAsConstant = false; // For assertion checking if (value.isConstant()) { JavaConstant constant = value.asJavaConstant(); - if (constant != null && kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { - // Only imm32 as long - return null; + if (constant != null) { + if (kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { + // Only imm32 as long + return null; + } + // A QWORD that can be encoded as int can be embedded as a constant + matchedAsConstant = kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && NumUtil.isInt(constant.asLong()); + } + if (kind == AMD64Kind.DWORD) { + // Any DWORD value should be embeddable as a constant + matchedAsConstant = true; } if (kind.isXMM()) { Debug.log("Skipping constant compares for float kinds"); return null; } } + boolean matchedAsConstantFinal = matchedAsConstant; - // emitCompareBranchMemory expects the memory on the right, so mirror the condition if - // that's not true. It might be mirrored again the actual compare is emitted but that's - // ok. + /* + * emitCompareBranchMemory expects the memory on the right, so mirror the condition if + * that's not true. It might be mirrored again the actual compare is emitted but that's ok. + */ Condition finalCondition = GraphUtil.unproxify(compare.getX()) == access ? cond.mirror() : cond; return new ComplexMatchResult() { @Override @@ -146,6 +166,11 @@ public class AMD64NodeMatchRules extends NodeMatchRules { boolean unorderedIsTrue = compare.unorderedIsTrue(); double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); Value other = operand(value); + /* + * Check that patterns which were matched as a constant actually end up seeing a + * constant in the LIR. + */ + assert !matchedAsConstantFinal || !LIRValueUtil.isVariable(other) : "expected constant value " + value; AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); getLIRGeneratorTool().emitCompareBranchMemory(kind, other, address, getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability); return null; @@ -153,7 +178,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { }; } - private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) { + private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, LIRLowerableAccess access) { LabelRef trueLabel = getLIRBlock(x.trueSuccessor()); LabelRef falseLabel = getLIRBlock(x.falseSuccessor()); double trueLabelProbability = x.probability(x.trueSuccessor()); @@ -181,15 +206,22 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } - protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) { + protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access, ValueKind addressKind) { return builder -> { AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); LIRFrameState state = getState(access); + if (addressKind != null) { + address = address.withKind(addressKind); + } return getArithmeticLIRGenerator().emitConvertMemoryOp(kind, op, size, address, state); }; } - private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { + protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) { + return emitConvertMemoryOp(kind, op, size, access, null); + } + + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits, ValueKind addressKind) { assert fromBits <= toBits && toBits <= 64; AMD64Kind kind = null; AMD64RMOp op; @@ -231,7 +263,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } if (kind != null && op != null) { - return emitConvertMemoryOp(kind, op, size, access); + return emitConvertMemoryOp(kind, op, size, access, addressKind); } return null; } @@ -244,7 +276,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(If (IntegerTest Read=access value))") @MatchRule("(If (IntegerTest FloatingRead=access value))") - public ComplexMatchResult integerTestBranchMemory(IfNode root, Access access, ValueNode value) { + public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) { return emitIntegerTestBranchMemory(root, value, access); } @@ -262,7 +294,67 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(If (PointerEquals=compare value FloatingRead=access))") @MatchRule("(If (ObjectEquals=compare value Read=access))") @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") - public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, Access access) { + public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { + return emitCompareBranchMemory(root, compare, value, access); + } + + @MatchRule("(If (ObjectEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))") + public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) { + assert compare.condition() == Condition.EQ; + if (value == cas.getExpectedValue() && cas.usages().count() == 1) { + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, Condition.EQ, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + + @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") + public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { + JavaConstant constant = value.asJavaConstant(); + assert compare.condition() == Condition.EQ; + if (constant != null && cas.usages().count() == 1) { + long constantValue = constant.asLong(); + boolean successIsTrue; + if (constantValue == 0) { + successIsTrue = false; + } else if (constantValue == 1) { + successIsTrue = true; + } else { + return null; + } + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); + Condition condition = successIsTrue ? Condition.EQ : Condition.NE; + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, condition, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + + @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") + public ComplexMatchResult ifLogicCas(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { return emitCompareBranchMemory(root, compare, value, access); } @@ -290,19 +382,19 @@ public class AMD64NodeMatchRules extends NodeMatchRules { return null; } - private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, Access access) { + private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } - private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, Access access) { + private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } @MatchRule("(Add value Read=access)") @MatchRule("(Add value FloatingRead=access)") - public ComplexMatchResult addMemory(ValueNode value, Access access) { + public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -319,7 +411,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Sub value Read=access)") @MatchRule("(Sub value FloatingRead=access)") - public ComplexMatchResult subMemory(ValueNode value, Access access) { + public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -336,7 +428,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Mul value Read=access)") @MatchRule("(Mul value FloatingRead=access)") - public ComplexMatchResult mulMemory(ValueNode value, Access access) { + public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -353,7 +445,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(And value Read=access)") @MatchRule("(And value FloatingRead=access)") - public ComplexMatchResult andMemory(ValueNode value, Access access) { + public ComplexMatchResult andMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -364,7 +456,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Or value Read=access)") @MatchRule("(Or value FloatingRead=access)") - public ComplexMatchResult orMemory(ValueNode value, Access access) { + public ComplexMatchResult orMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -375,7 +467,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Xor value Read=access)") @MatchRule("(Xor value FloatingRead=access)") - public ComplexMatchResult xorMemory(ValueNode value, Access access) { + public ComplexMatchResult xorMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -395,20 +487,44 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(SignExtend Read=access)") @MatchRule("(SignExtend FloatingRead=access)") - public ComplexMatchResult signExtend(SignExtendNode root, Access access) { - return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits()); + public ComplexMatchResult signExtend(SignExtendNode root, LIRLowerableAccess access) { + return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits(), null); } @MatchRule("(ZeroExtend Read=access)") @MatchRule("(ZeroExtend FloatingRead=access)") - public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) { + public ComplexMatchResult zeroExtend(ZeroExtendNode root, LIRLowerableAccess access) { AMD64Kind memoryKind = getMemoryKind(access); return builder -> getArithmeticLIRGenerator().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } + @MatchRule("(Narrow Read=access)") + @MatchRule("(Narrow FloatingRead=access)") + public ComplexMatchResult narrowRead(NarrowNode root, LIRLowerableAccess access) { + return new ComplexMatchResult() { + @Override + public Value evaluate(NodeLIRBuilder builder) { + AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); + LIRKind addressKind = LIRKind.combineDerived(getLIRGeneratorTool().getLIRKind(root.asNode().stamp()), + address.getBase(), address.getIndex()); + AMD64AddressValue newAddress = address.withKind(addressKind); + LIRKind readKind = getLIRGeneratorTool().getLIRKind(root.stamp()); + return getArithmeticLIRGenerator().emitZeroExtendMemory((AMD64Kind) readKind.getPlatformKind(), + root.getResultBits(), newAddress, getState(access)); + } + }; + } + + @MatchRule("(SignExtend (Narrow=narrow Read=access))") + @MatchRule("(SignExtend (Narrow=narrow FloatingRead=access))") + public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode narrow, LIRLowerableAccess access) { + LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp()); + return emitSignExtendMemory(access, narrow.getResultBits(), root.getResultBits(), kind); + } + @MatchRule("(FloatConvert Read=access)") @MatchRule("(FloatConvert FloatingRead=access)") - public ComplexMatchResult floatConvert(FloatConvertNode root, Access access) { + public ComplexMatchResult floatConvert(FloatConvertNode root, LIRLowerableAccess access) { switch (root.getFloatConvert()) { case D2F: return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSD2SS, SD, access); @@ -437,7 +553,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Reinterpret Read=access)") @MatchRule("(Reinterpret FloatingRead=access)") - public ComplexMatchResult reinterpret(ReinterpretNode root, Access access) { + public ComplexMatchResult reinterpret(ReinterpretNode root, LIRLowerableAccess access) { return builder -> { LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp()); return emitReinterpretMemory(kind, access); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java similarity index 80% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java index 99ecbb711c9..e8c9936dcbd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java @@ -22,22 +22,23 @@ */ package org.graalvm.compiler.core.amd64; -import org.graalvm.compiler.java.DefaultSuitesProvider; +import org.graalvm.compiler.java.DefaultSuitesCreator; import org.graalvm.compiler.lir.amd64.phases.StackMoveOptimizationPhase; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -public class AMD64SuitesProvider extends DefaultSuitesProvider { +public class AMD64SuitesCreator extends DefaultSuitesCreator { - public AMD64SuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public AMD64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } @Override - public LIRSuites createLIRSuites() { - LIRSuites lirSuites = super.createLIRSuites(); - if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue()) { + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites lirSuites = super.createLIRSuites(options); + if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue(options)) { /* Note: this phase must be inserted after RedundantMoveElimination */ lirSuites.getPostAllocationOptimizationStage().appendPhase(new StackMoveOptimizationPhase()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java new file mode 100644 index 00000000000..0711203bb47 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java @@ -0,0 +1,41 @@ +/* + * 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.core.common; + +/** + * A {@linkplain RetryableBailoutException} that will be thrown if an on-going compilation in the + * compiler was cancelled. + */ +public final class CancellationBailoutException extends RetryableBailoutException { + + private static final long serialVersionUID = 6551793589275293360L; + + public CancellationBailoutException() { + super("Compilation cancelled."); + } + + public static void cancelCompilation() { + throw new CancellationBailoutException(); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java deleted file mode 100644 index 072372e5c7c..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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; - -import static org.graalvm.compiler.core.common.CollectionsFactory.Mode.STANDARD; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -/** - * Factory for creating collection objects used during compilation. - */ -public class CollectionsFactory { - - private static final ThreadLocal tl = new ThreadLocal<>(); - - public static class ModeScope implements AutoCloseable { - private final Mode previousMode; - - public ModeScope(Mode previousMode) { - this.previousMode = previousMode; - } - - @Override - public void close() { - tl.set(previousMode); - } - } - - /** - * Constants denoting what type of collections are {@link CollectionsFactory#getMode() - * currently} returned by the factory. - */ - public enum Mode { - /** - * Denotes standard collections such as {@link HashSet} and {@link HashMap}. - */ - STANDARD, - - /** - * Denotes collections that have a deterministic iteration order over their keys/entries. - */ - DETERMINISTIC_ITERATION_ORDER; - } - - /** - * Gets the current mode determining the type of collection objects created by this factory. - */ - public static Mode getMode() { - Mode mode = tl.get(); - return mode == null ? Mode.STANDARD : mode; - } - - /** - * Updates the mode for the current thread. - * - * @return an object which when {@linkplain ModeScope#close() closed} will revert the mode of - * the current thread to the state before calling this method - */ - public static ModeScope changeMode(Mode mode) { - Mode previousMode = tl.get(); - tl.set(mode); - return new ModeScope(previousMode); - } - - public static HashMap newMap() { - return getMode() == STANDARD ? new HashMap<>() : new LinkedHashMap<>(); - } - - public static HashMap newMap(Map m) { - return getMode() == STANDARD ? new HashMap<>(m) : new LinkedHashMap<>(m); - } - - public static HashMap newMap(int initialCapacity) { - return getMode() == STANDARD ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity); - } - - public static Map newIdentityMap() { - return getMode() == STANDARD ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>(); - } - - public static Map newIdentityMap(int expectedMaxSize) { - return getMode() == STANDARD ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>(); - } - - public static Map newIdentityMap(Map m) { - return getMode() == STANDARD ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m); - } - - /** - * Creates a set. If the current thread is {@linkplain CollectionsFactory#getMode() using} - * {@link Mode#DETERMINISTIC_ITERATION_ORDER} collections, the returned set will have an - * iteration order determined by the order in which elements are inserted in the set. - */ - public static Set newSet() { - return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>() : new LinkedHashSet<>(); - } - - /** - * @see #newSet() - */ - public static Set newSet(Collection c) { - return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>(c) : new LinkedHashSet<>(c); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java similarity index 75% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java index 9a0a8d22215..4eac53452cb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,20 +20,18 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.hotspot; +package org.graalvm.compiler.core.common; /** * A compact representation of the different encoding strategies for Objects and metadata. */ -public class CompressEncoding { - public final long base; - public final int shift; - public final int alignment; +public final class CompressEncoding { + private final long base; + private final int shift; - CompressEncoding(long base, int shift, int alignment) { + public CompressEncoding(long base, int shift) { this.base = base; this.shift = shift; - this.alignment = alignment; } public int compress(long ptr) { @@ -44,6 +42,22 @@ public class CompressEncoding { } } + public boolean hasBase() { + return base != 0; + } + + public boolean hasShift() { + return shift != 0; + } + + public long getBase() { + return base; + } + + public int getShift() { + return shift; + } + public long uncompress(int ptr) { if (ptr == 0) { return 0L; @@ -54,14 +68,13 @@ public class CompressEncoding { @Override public String toString() { - return "base: " + base + " shift: " + shift + " alignment: " + alignment; + return "base: " + base + " shift: " + shift; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + alignment; result = prime * result + (int) (base ^ (base >>> 32)); result = prime * result + shift; return result; @@ -71,7 +84,7 @@ public class CompressEncoding { public boolean equals(Object obj) { if (obj instanceof CompressEncoding) { CompressEncoding other = (CompressEncoding) obj; - return alignment == other.alignment && base == other.base && shift == other.shift; + return base == other.base && shift == other.shift; } else { return false; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java index 68d158db3b8..7b4665e735b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.core.common; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionKey; /** * This class encapsulates options that control the behavior of the Graal compiler. @@ -34,250 +34,242 @@ import org.graalvm.compiler.options.StableOptionValue; public final class GraalOptions { @Option(help = "Use compiler intrinsifications.", type = OptionType.Debug) - public static final OptionValue Intrinsify = new OptionValue<>(true); + public static final OptionKey Intrinsify = new OptionKey<>(true); @Option(help = "Inline calls with monomorphic type profile.", type = OptionType.Expert) - public static final OptionValue InlineMonomorphicCalls = new OptionValue<>(true); + public static final OptionKey InlineMonomorphicCalls = new OptionKey<>(true); @Option(help = "Inline calls with polymorphic type profile.", type = OptionType.Expert) - public static final OptionValue InlinePolymorphicCalls = new OptionValue<>(true); + public static final OptionKey InlinePolymorphicCalls = new OptionKey<>(true); @Option(help = "Inline calls with megamorphic type profile (i.e., not all types could be recorded).", type = OptionType.Expert) - public static final OptionValue InlineMegamorphicCalls = new OptionValue<>(true); + public static final OptionKey InlineMegamorphicCalls = new OptionKey<>(true); @Option(help = "Maximum desired size of the compiler graph in nodes.", type = OptionType.User) - public static final OptionValue MaximumDesiredSize = new OptionValue<>(20000); + public static final OptionKey MaximumDesiredSize = new OptionKey<>(20000); @Option(help = "Minimum probability for methods to be inlined for megamorphic type profiles.", type = OptionType.Expert) - public static final OptionValue MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D); + public static final OptionKey MegamorphicInliningMinMethodProbability = new OptionKey<>(0.33D); @Option(help = "Maximum level of recursive inlining.", type = OptionType.Expert) - public static final OptionValue MaximumRecursiveInlining = new OptionValue<>(5); + public static final OptionKey MaximumRecursiveInlining = new OptionKey<>(5); @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.", type = OptionType.Expert) - public static final OptionValue TrivialInliningSize = new OptionValue<>(10); + public static final OptionKey TrivialInliningSize = new OptionKey<>(10); @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.", type = OptionType.Expert) - public static final OptionValue MaximumInliningSize = new OptionValue<>(300); + public static final OptionKey MaximumInliningSize = new OptionKey<>(300); @Option(help = "If the previous low-level graph size of the method exceeds the threshold, it is not inlined.", type = OptionType.Expert) - public static final OptionValue SmallCompiledLowLevelGraphSize = new OptionValue<>(300); + public static final OptionKey SmallCompiledLowLevelGraphSize = new OptionKey<>(300); @Option(help = "", type = OptionType.Expert) - public static final OptionValue LimitInlinedInvokes = new OptionValue<>(5.0); + public static final OptionKey LimitInlinedInvokes = new OptionKey<>(5.0); @Option(help = "", type = OptionType.Expert) - public static final OptionValue InlineEverything = new OptionValue<>(false); + public static final OptionKey InlineEverything = new OptionKey<>(false); // escape analysis settings @Option(help = "", type = OptionType.Debug) - public static final OptionValue PartialEscapeAnalysis = new OptionValue<>(true); + public static final OptionKey PartialEscapeAnalysis = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalysisIterations = new OptionValue<>(2); + public static final OptionKey EscapeAnalysisIterations = new OptionKey<>(2); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalysisLoopCutoff = new OptionValue<>(20); + public static final OptionKey EscapeAnalysisLoopCutoff = new OptionKey<>(20); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalyzeOnly = new OptionValue<>(null); + public static final OptionKey EscapeAnalyzeOnly = new OptionKey<>(null); @Option(help = "", type = OptionType.Expert) - public static final OptionValue MaximumEscapeAnalysisArrayLength = new OptionValue<>(32); + public static final OptionKey MaximumEscapeAnalysisArrayLength = new OptionKey<>(32); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PEAInliningHints = new OptionValue<>(false); + public static final OptionKey PEAInliningHints = new OptionKey<>(false); @Option(help = "", type = OptionType.Expert) - public static final OptionValue TailDuplicationProbability = new OptionValue<>(0.5); + public static final OptionKey TailDuplicationProbability = new OptionKey<>(0.5); @Option(help = "", type = OptionType.Expert) - public static final OptionValue TailDuplicationTrivialSize = new OptionValue<>(1); + public static final OptionKey TailDuplicationTrivialSize = new OptionKey<>(1); @Option(help = "", type = OptionType.Expert) - public static final OptionValue DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); + public static final OptionKey DeoptsToDisableOptimisticOptimization = new OptionKey<>(40); @Option(help = "", type = OptionType.Debug) - public static final OptionValue LoopPeeling = new OptionValue<>(true); + public static final OptionKey LoopPeeling = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ReassociateInvariants = new OptionValue<>(true); + public static final OptionKey ReassociateInvariants = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue FullUnroll = new OptionValue<>(true); + public static final OptionKey FullUnroll = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue LoopUnswitch = new OptionValue<>(true); + public static final OptionKey LoopUnswitch = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue MinimumPeelProbability = new OptionValue<>(0.35f); + public static final OptionKey MinimumPeelProbability = new OptionKey<>(0.35f); @Option(help = "", type = OptionType.Expert) - public static final OptionValue LoopMaxUnswitch = new OptionValue<>(3); + public static final OptionKey LoopMaxUnswitch = new OptionKey<>(3); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseLoopLimitChecks = new OptionValue<>(true); + public static final OptionKey UseLoopLimitChecks = new OptionKey<>(true); // debugging settings @Option(help = "", type = OptionType.Debug) - public static final OptionValue ZapStackOnMethodEntry = new OptionValue<>(false); + public static final OptionKey ZapStackOnMethodEntry = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue DeoptALot = new OptionValue<>(false); + public static final OptionKey DeoptALot = new OptionKey<>(false); @Option(help = "Stress the code emitting explicit exception throwing code.", type = OptionType.Debug) - public static final OptionValue StressExplicitExceptionCode = new OptionValue<>(false); + public static final OptionKey StressExplicitExceptionCode = new OptionKey<>(false); @Option(help = "Stress the code emitting invokes with explicit exception edges.", type = OptionType.Debug) - public static final OptionValue StressInvokeWithExceptionNode = new OptionValue<>(false); + public static final OptionKey StressInvokeWithExceptionNode = new OptionKey<>(false); + + @Option(help = "Stress the code by emitting reads at earliest instead of latest point.", type = OptionType.Debug) + public static final OptionKey StressTestEarlyReads = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue VerifyPhases = new OptionValue<>(false); + public static final OptionKey VerifyPhases = new OptionKey<>(false); // Debug settings: @Option(help = "", type = OptionType.Debug) - public static final OptionValue GCDebugStartCycle = new OptionValue<>(-1); + public static final OptionKey GCDebugStartCycle = new OptionKey<>(-1); @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug) - public static final OptionValue VerifyHeapAtReturn = new OptionValue<>(false); + public static final OptionKey VerifyHeapAtReturn = new OptionKey<>(false); // Other printing settings @Option(help = "Print profiling information when parsing a method's bytecode", type = OptionType.Debug) - public static final OptionValue PrintProfilingInformation = new OptionValue<>(false); + public static final OptionKey PrintProfilingInformation = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final StableOptionValue TraceEscapeAnalysis = new StableOptionValue<>(false); + public static final OptionKey TraceEscapeAnalysis = new OptionKey<>(false); // HotSpot command line options @Option(help = "Print inlining optimizations", type = OptionType.Debug) - public static final OptionValue HotSpotPrintInlining = new OptionValue<>(false); + public static final OptionKey HotSpotPrintInlining = new OptionKey<>(false); // Register allocator debugging @Option(help = "Comma separated list of registers that register allocation is limited to.", type = OptionType.Debug) - public static final OptionValue RegisterPressure = new OptionValue<>(null); + public static final OptionKey RegisterPressure = new OptionKey<>(null); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ConditionalElimination = new OptionValue<>(true); + public static final OptionKey ConditionalElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue RemoveNeverExecutedCode = new OptionValue<>(true); + public static final OptionKey RawConditionalElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseExceptionProbability = new OptionValue<>(true); + public static final OptionKey ReplaceInputsWithConstantsBasedOnStamps = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseExceptionProbabilityForOperations = new OptionValue<>(true); + public static final OptionKey RemoveNeverExecutedCode = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OmitHotExceptionStacktrace = new OptionValue<>(false); + public static final OptionKey UseExceptionProbability = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue GenSafepoints = new OptionValue<>(true); + public static final OptionKey OmitHotExceptionStacktrace = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue GenLoopSafepoints = new OptionValue<>(true); + public static final OptionKey GenSafepoints = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseTypeCheckHints = new OptionValue<>(true); + public static final OptionKey GenLoopSafepoints = new OptionKey<>(true); + + @Option(help = "", type = OptionType.Debug) + public static final OptionKey UseTypeCheckHints = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue InlineVTableStubs = new OptionValue<>(true); + public static final OptionKey InlineVTableStubs = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AlwaysInlineVTableStubs = new OptionValue<>(false); + public static final OptionKey AlwaysInlineVTableStubs = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ResolveClassBeforeStaticInvoke = new OptionValue<>(false); + public static final OptionKey ResolveClassBeforeStaticInvoke = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue CanOmitFrame = new OptionValue<>(true); + public static final OptionKey CanOmitFrame = new OptionKey<>(true); // Ahead of time compilation @Option(help = "Try to avoid emitting code where patching is required", type = OptionType.Expert) - public static final OptionValue ImmutableCode = new OptionValue<>(false); + public static final OptionKey ImmutableCode = new OptionKey<>(false); @Option(help = "Generate position independent code", type = OptionType.Expert) - public static final OptionValue GeneratePIC = new OptionValue<>(false); + public static final OptionKey GeneratePIC = new OptionKey<>(false); @Option(help = "", type = OptionType.Expert) - public static final OptionValue CallArrayCopy = new OptionValue<>(true); + public static final OptionKey CallArrayCopy = new OptionKey<>(true); // Runtime settings @Option(help = "", type = OptionType.Expert) - public static final OptionValue SupportJsrBytecodes = new OptionValue<>(true); + public static final OptionKey SupportJsrBytecodes = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue OptAssumptions = new OptionValue<>(true); + public static final OptionKey OptAssumptions = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptConvertDeoptsToGuards = new OptionValue<>(true); + public static final OptionKey OptConvertDeoptsToGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptReadElimination = new OptionValue<>(true); + public static final OptionKey OptReadElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ReadEliminationMaxLoopVisits = new OptionValue<>(5); + public static final OptionKey ReadEliminationMaxLoopVisits = new OptionKey<>(5); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptDeoptimizationGrouping = new OptionValue<>(true); + public static final OptionKey OptDeoptimizationGrouping = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptScheduleOutOfLoops = new OptionValue<>(true); + public static final OptionKey OptScheduleOutOfLoops = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptEliminateGuards = new OptionValue<>(true); + public static final OptionKey OptEliminateGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptImplicitNullChecks = new OptionValue<>(true); + public static final OptionKey OptImplicitNullChecks = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptClearNonLiveLocals = new OptionValue<>(true); + public static final OptionKey OptClearNonLiveLocals = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptLoopTransform = new OptionValue<>(true); + public static final OptionKey OptLoopTransform = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptFloatingReads = new OptionValue<>(true); + public static final OptionKey OptFloatingReads = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptEliminatePartiallyRedundantGuards = new OptionValue<>(true); + public static final OptionKey OptEliminatePartiallyRedundantGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptFilterProfiledTypes = new OptionValue<>(true); + public static final OptionKey OptFilterProfiledTypes = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptDevirtualizeInvokesOptimistically = new OptionValue<>(true); - - @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptPushThroughPi = new OptionValue<>(true); + public static final OptionKey OptDevirtualizeInvokesOptimistically = new OptionKey<>(true); @Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug) - public static final OptionValue MatchExpressions = new OptionValue<>(true); + public static final OptionKey MatchExpressions = new OptionKey<>(true); @Option(help = "Enable counters for various paths in snippets.", type = OptionType.Debug) - public static final OptionValue SnippetCounters = new OptionValue<>(false); + public static final OptionKey SnippetCounters = new OptionKey<>(false); @Option(help = "Eagerly construct extra snippet info.", type = OptionType.Debug) - public static final OptionValue EagerSnippets = new OptionValue<>(false); + public static final OptionKey EagerSnippets = new OptionKey<>(false); @Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug) - public static final OptionValue UseSnippetGraphCache = new OptionValue<>(true); + public static final OptionKey UseSnippetGraphCache = new OptionKey<>(true); - @Option(help = "Enable expensive assertions", type = OptionType.Debug) - public static final OptionValue DetailedAsserts = new StableOptionValue() { - @Override - protected Boolean defaultValue() { - boolean enabled = false; - // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this) - assert (enabled = true) == true; - return enabled; - } - }; - - @Option(help = "Enable Graal instrumentation") - public static final OptionValue UseGraalInstrumentation = new OptionValue<>(false); + @Option(help = "Enable expensive assertions.", type = OptionType.Debug) + public static final OptionKey DetailedAsserts = new OptionKey<>(Assertions.ENABLED); @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug) - public static final OptionValue TraceRA = new OptionValue<>(false); + public static final OptionKey TraceRA = new OptionKey<>(false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java index 2b26f8f2506..688a328a006 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.common; -import java.util.ArrayList; +import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.AllocatableValue; @@ -169,23 +169,6 @@ public final class LIRKind extends ValueKind { return inputs[0].getValueKind(LIRKind.class); } - /** - * Merge the types of the inputs. The result will have the {@link PlatformKind} of one of the - * inputs. If all inputs are values (references), the result is a value (reference). Otherwise, - * the result is an unknown reference. - * - * This method should be used to construct the result {@link LIRKind} of merge operation that - * does not modify values (e.g. phis). - */ - public static LIRKind merge(Value... inputs) { - assert inputs.length > 0; - ArrayList kinds = new ArrayList<>(inputs.length); - for (int i = 0; i < inputs.length; i++) { - kinds.add(inputs[i].getValueKind(LIRKind.class)); - } - return merge(kinds); - } - /** * Helper method to construct derived reference kinds. Returns the base value of a reference or * derived reference. For values it returns {@code null}, and for unknown references it returns @@ -228,62 +211,62 @@ public final class LIRKind extends ValueKind { } /** - * @see #merge(Value...) + * Merges the reference information of the inputs. The result will have the {@link PlatformKind} + * of {@code mergeKind}. If all inputs are values (references), the result is a value + * (reference). Otherwise, the result is an unknown reference. + * + * The correctness of the {@link PlatformKind} is not verified. */ - public static LIRKind merge(Iterable kinds) { - LIRKind mergeKind = null; + public static LIRKind mergeReferenceInformation(LIRKind mergeKind, LIRKind inputKind) { + assert mergeKind != null; + assert inputKind != null; - for (LIRKind kind : kinds) { + if (mergeKind.isUnknownReference()) { + /** + * {@code mergeKind} is an unknown reference, therefore the result can only be also an + * unknown reference. + */ + return mergeKind; + } - if (kind.isUnknownReference()) { - /** - * Kind is an unknown reference, therefore the result can only be also an unknown - * reference. + if (mergeKind.isValue()) { + /* {@code mergeKind} is a value. */ + if (!inputKind.isValue()) { + /* + * Inputs consists of values and references. Make the result an unknown reference. */ - mergeKind = kind; - break; + return mergeKind.makeUnknownReference(); } - if (mergeKind == null) { - mergeKind = kind; - continue; - } - - if (kind.isValue()) { - /* Kind is a value. */ - if (mergeKind.referenceMask != 0) { - /* - * Inputs consists of values and references. Make the result an unknown - * reference. - */ - mergeKind = mergeKind.makeUnknownReference(); - break; - } - /* Check that other inputs are also values. */ - } else { - /* Kind is a reference. */ - if (mergeKind.referenceMask != kind.referenceMask) { - /* - * Reference maps do not match so the result can only be an unknown reference. - */ - mergeKind = mergeKind.makeUnknownReference(); - break; - } - } - + return mergeKind; + } + /* {@code mergeKind} is a reference. */ + if (mergeKind.referenceMask != inputKind.referenceMask) { + /* + * Reference masks do not match so the result can only be an unknown reference. + */ + return mergeKind.makeUnknownReference(); } - assert mergeKind != null && verifyMerge(mergeKind, kinds); - // all inputs are values or references, just return one of them + /* Both are references. */ + if (mergeKind.isDerivedReference()) { + if (inputKind.isDerivedReference() && mergeKind.getDerivedReferenceBase().equals(inputKind.getDerivedReferenceBase())) { + /* Same reference base so they must be equal. */ + return mergeKind; + } + /* Base pointers differ. Make the result an unknown reference. */ + return mergeKind.makeUnknownReference(); + } + if (inputKind.isDerivedReference()) { + /* + * {@code mergeKind} is not derived but {@code inputKind} is. Make the result an unknown + * reference. + */ + return mergeKind.makeUnknownReference(); + } + /* Both are not derived references so they must be equal. */ return mergeKind; } - private static boolean verifyMerge(LIRKind mergeKind, Iterable kinds) { - for (LIRKind kind : kinds) { - assert mergeKind == null || verifyMoveKinds(mergeKind, kind) : String.format("Input kinds do not match %s vs. %s", mergeKind, kind); - } - return true; - } - /** * Create a new {@link LIRKind} with the same reference information and a new * {@linkplain #getPlatformKind platform kind}. If the new kind is a longer vector than this, @@ -447,6 +430,7 @@ public final class LIRKind extends ValueKind { final int prime = 31; int result = 1; result = prime * result + ((getPlatformKind() == null) ? 0 : getPlatformKind().hashCode()); + result = prime * result + ((getDerivedReferenceBase() == null) ? 0 : getDerivedReferenceBase().hashCode()); result = prime * result + referenceMask; return result; } @@ -461,16 +445,37 @@ public final class LIRKind extends ValueKind { } LIRKind other = (LIRKind) obj; - return getPlatformKind() == other.getPlatformKind() && referenceMask == other.referenceMask; + if (getPlatformKind() != other.getPlatformKind() || referenceMask != other.referenceMask) { + return false; + } + if (isDerivedReference()) { + if (!other.isDerivedReference()) { + return false; + } + return getDerivedReferenceBase().equals(other.getDerivedReferenceBase()); + } + // `this` is not a derived reference + if (other.isDerivedReference()) { + return false; + } + return true; } - public static boolean verifyMoveKinds(ValueKind dst, ValueKind src) { + public static boolean verifyMoveKinds(ValueKind dst, ValueKind src, RegisterAllocationConfig config) { if (src.equals(dst)) { return true; } - if (src.getPlatformKind().equals(dst.getPlatformKind())) { - return !isUnknownReference(src) || isUnknownReference(dst); + if (isUnknownReference(dst) || isValue(dst) && isValue(src)) { + PlatformKind srcPlatformKind = src.getPlatformKind(); + PlatformKind dstPlatformKind = dst.getPlatformKind(); + if (srcPlatformKind.equals(dstPlatformKind)) { + return true; + } + // if the register category matches it should be fine, although the kind is different + return config.getRegisterCategory(srcPlatformKind).equals(config.getRegisterCategory(dstPlatformKind)); } + // reference information mismatch return false; } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java deleted file mode 100644 index 7c1aca0bdc6..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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; - -import java.util.AbstractSet; -import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.Consumer; - -/** - * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of - * ensuring a deterministic execution order during a capturing compilation. - */ -final class LinkedIdentityHashMap implements Map { - - private final LinkedHashMap, V> map; - - LinkedIdentityHashMap() { - map = new LinkedHashMap<>(); - } - - LinkedIdentityHashMap(Map m) { - map = new LinkedHashMap<>(m.size()); - putAll(m); - } - - LinkedIdentityHashMap(int expectedMaxSize) { - map = new LinkedHashMap<>(expectedMaxSize); - } - - /** - * Wrapper for an object that gives uses the object's identity for the purpose of equality - * comparisons and computing a hash code. - */ - static final class Id { - final T object; - - Id(T object) { - assert object != null; - this.object = object; - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object obj) { - return obj instanceof Id && ((Id) obj).object == object; - } - - @Override - public int hashCode() { - return System.identityHashCode(object); - } - } - - @Override - public int size() { - return map.size(); - } - - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return map.containsKey(id(key)); - } - - @SuppressWarnings("unchecked") - private Id id(Object key) { - if (key == null) { - return null; - } - return new Id<>((K) key); - } - - @Override - public boolean containsValue(Object value) { - return map.containsValue(value); - } - - @Override - public V get(Object key) { - return map.get(id(key)); - } - - @Override - public V put(K key, V value) { - return map.put(id(key), value); - } - - @Override - public V remove(Object key) { - return map.remove(id(key)); - } - - @Override - @SuppressWarnings("unchecked") - public void putAll(Map m) { - if (m == null) { - throw new NullPointerException(); - } - if (m.getClass() == getClass()) { - LinkedIdentityHashMap that = (LinkedIdentityHashMap) m; - map.putAll(that.map); - - } else { - for (K key : m.keySet()) { - map.put(id(key), m.get(key)); - } - } - } - - @Override - public void clear() { - map.clear(); - } - - final class KeySet extends AbstractSet { - @Override - public int size() { - return map.size(); - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public Iterator iterator() { - return new Iterator() { - final Iterator> i = map.keySet().iterator(); - - @Override - public boolean hasNext() { - return i.hasNext(); - } - - @Override - public K next() { - return i.next().object; - } - - @Override - public void remove() { - i.remove(); - } - }; - } - - @Override - public boolean contains(Object o) { - return containsKey(o); - } - - @Override - public boolean remove(Object o) { - return LinkedIdentityHashMap.this.remove(o) != null; - } - - @Override - public Spliterator spliterator() { - return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT); - } - - @Override - public void forEach(Consumer action) { - throw new UnsupportedOperationException(); - } - } - - @Override - public Set keySet() { - return new KeySet(); - } - - @Override - public Collection values() { - return map.values(); - } - - final class EntrySet extends AbstractSet> { - @Override - public int size() { - return map.size(); - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public Iterator> iterator() { - return new Iterator>() { - final Iterator, V>> i = map.entrySet().iterator(); - - @Override - public boolean hasNext() { - return i.hasNext(); - } - - @Override - public Map.Entry next() { - Map.Entry, V> e = i.next(); - return new Map.Entry() { - - @Override - public K getKey() { - return e.getKey().object; - } - - @Override - public V getValue() { - return e.getValue(); - } - - @Override - public V setValue(V value) { - return e.setValue(value); - } - }; - } - - @Override - public void remove() { - i.remove(); - } - }; - } - - @Override - public boolean contains(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public Spliterator> spliterator() { - throw new UnsupportedOperationException(); - } - - @Override - public void forEach(Consumer> action) { - throw new UnsupportedOperationException(); - } - } - - @Override - public Set> entrySet() { - return new EntrySet(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java similarity index 83% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java index 5966c04c6c9..f34ce87ff4f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java @@ -20,10 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.asm; +package org.graalvm.compiler.core.common; // JaCoCo Exclude +import jdk.vm.ci.code.CodeUtil; + /** * A collection of static utility functions that check ranges of numbers. */ @@ -183,4 +185,43 @@ public class NumUtil { return 0xFFFFFFFFFFFFFFFFL; } } + + /** + * Get the minimum value representable in a {@code bits} bit signed integer. + */ + public static long minValue(int bits) { + return CodeUtil.minValue(bits); + } + + /** + * Get the maximum value representable in a {@code bits} bit signed integer. + */ + public static long maxValue(int bits) { + return CodeUtil.maxValue(bits); + } + + /** + * Get the maximum value representable in a {@code bits} bit unsigned integer. + */ + public static long maxValueUnsigned(int bits) { + return getNbitNumberLong(bits); + } + + public static long maxUnsigned(long a, long b) { + if (Long.compareUnsigned(a, b) > 0) { + return b; + } + return a; + } + + public static long minUnsigned(long a, long b) { + if (Long.compareUnsigned(a, b) > 0) { + return a; + } + return b; + } + + public static boolean sameSign(long a, long b) { + return a < 0 == b < 0; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java similarity index 97% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java index 52da33abd57..2e2ef19c59c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.common; +package org.graalvm.compiler.core.common; import jdk.vm.ci.code.BailoutException; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java similarity index 97% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java index 61ef7303147..da3daf35f42 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.common; +package org.graalvm.compiler.core.common; import jdk.vm.ci.code.BailoutException; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java index 91ff0154db0..4b51e378daa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java @@ -22,18 +22,16 @@ */ package org.graalvm.compiler.core.common.alloc; -import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; - -import java.util.HashMap; -import java.util.Map; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.Register.RegisterCategory; import jdk.vm.ci.code.RegisterArray; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.meta.PlatformKind; -import org.graalvm.compiler.core.common.GraalOptions; - /** * Configuration for register allocation. This is different to {@link RegisterConfig} as it only * returns registers specified by {@link GraalOptions#RegisterPressure}. @@ -82,11 +80,10 @@ public class RegisterAllocationConfig { } protected RegisterArray initAllocatable(RegisterArray registers) { - if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) { - String[] names = RegisterPressure.getValue().split(","); - Register[] regs = new Register[names.length]; - for (int i = 0; i < names.length; i++) { - regs[i] = findRegister(names[i], registers); + if (allocationRestrictedTo != null) { + Register[] regs = new Register[allocationRestrictedTo.length]; + for (int i = 0; i < allocationRestrictedTo.length; i++) { + regs[i] = findRegister(allocationRestrictedTo[i], registers); } return new RegisterArray(regs); } @@ -95,12 +92,18 @@ public class RegisterAllocationConfig { } protected final RegisterConfig registerConfig; - private final Map categorized = new HashMap<>(); + private final EconomicMap categorized = EconomicMap.create(Equivalence.DEFAULT); + private final String[] allocationRestrictedTo; private RegisterArray cachedRegisters; - public RegisterAllocationConfig(RegisterConfig registerConfig) { + /** + * @param allocationRestrictedTo if not {@code null}, register allocation will be restricted to + * registers whose names appear in this array + */ + public RegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { assert registerConfig != null; this.registerConfig = registerConfig; + this.allocationRestrictedTo = allocationRestrictedTo; } /** @@ -118,6 +121,13 @@ public class RegisterAllocationConfig { return ret; } + /** + * Gets the {@link RegisterCategory} for the given {@link PlatformKind}. + */ + public RegisterCategory getRegisterCategory(PlatformKind kind) { + return getAllocatableRegisters(kind).allocatableRegisters[0].getRegisterCategory(); + } + protected AllocatableRegisters createAllocatableRegisters(RegisterArray registers) { int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java index 2e09be8d3a7..d25cddb2d4e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java @@ -35,7 +35,7 @@ public final class TraceStatisticsPrinter { @SuppressWarnings("try") public static void printTraceStatistics(TraceBuilderResult result, String compilationUnitName) { try (Scope s = Debug.scope("DumpTraceStatistics")) { - if (Debug.isLogEnabled(Debug.VERBOSE_LOG_LEVEL)) { + if (Debug.isLogEnabled(Debug.VERBOSE_LEVEL)) { print(result, compilationUnitName); } } catch (Throwable e) { @@ -48,9 +48,9 @@ public final class TraceStatisticsPrinter { List traces = result.getTraces(); int numTraces = traces.size(); - try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "")) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "%s", compilationUnitName != null ? compilationUnitName : "null"); - try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "")) { + try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "")) { + Debug.log(Debug.VERBOSE_LEVEL, "%s", compilationUnitName != null ? compilationUnitName : "null"); + try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LEVEL, "")) { printRawLine("tracenumber", "total", "min", "max", "numBlocks"); for (int i = 0; i < numTraces; i++) { AbstractBlockBase[] t = traces.get(i).getBlocks(); @@ -70,14 +70,14 @@ public final class TraceStatisticsPrinter { printLine(i, total, min, max, t.length); } } - Debug.log(Debug.VERBOSE_LOG_LEVEL, ""); + Debug.log(Debug.VERBOSE_LEVEL, ""); } - Debug.log(Debug.VERBOSE_LOG_LEVEL, ""); + Debug.log(Debug.VERBOSE_LEVEL, ""); } private static void printRawLine(Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); + Debug.log(Debug.VERBOSE_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); } private static void printLine(int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java index 546dbd0dc11..6b1f94926b6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java @@ -343,116 +343,7 @@ public enum Condition { if (lt instanceof PrimitiveConstant) { PrimitiveConstant lp = (PrimitiveConstant) lt; PrimitiveConstant rp = (PrimitiveConstant) rt; - switch (lp.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: { - int x = lp.asInt(); - int y = rp.asInt(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalError("expected condition: %s", this); - } - } - case Long: { - long x = lp.asLong(); - long y = rp.asLong(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalError("expected condition: %s", this); - } - } - case Float: { - float x = lp.asFloat(); - float y = rp.asFloat(); - if (Float.isNaN(x) || Float.isNaN(y)) { - return unorderedIsTrue; - } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalError("expected condition: %s", this); - } - } - case Double: { - double x = lp.asDouble(); - double y = rp.asDouble(); - if (Double.isNaN(x) || Double.isNaN(y)) { - return unorderedIsTrue; - } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalError("expected condition: %s", this); - } - } - default: - throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this); - } + return foldCondition(lp, rp, unorderedIsTrue); } else { Boolean equal = constantReflection.constantEquals(lt, rt); if (equal == null) { @@ -469,6 +360,128 @@ public enum Condition { } } + /** + * Attempts to fold a comparison between two primitive constants and return the result. + * + * @param lp the constant on the left side of the comparison + * @param rp the constant on the right side of the comparison + * @param unorderedIsTrue true if an undecided float comparison should result in "true" + * @return true if the comparison is known to be true, false if the comparison is known to be + * false + */ + public boolean foldCondition(PrimitiveConstant lp, PrimitiveConstant rp, boolean unorderedIsTrue) { + switch (lp.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: { + int x = lp.asInt(); + int y = rp.asInt(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalError("expected condition: %s", this); + } + } + case Long: { + long x = lp.asLong(); + long y = rp.asLong(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalError("expected condition: %s", this); + } + } + case Float: { + float x = lp.asFloat(); + float y = rp.asFloat(); + if (Float.isNaN(x) || Float.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalError("expected condition: %s", this); + } + } + case Double: { + double x = lp.asDouble(); + double y = rp.asDouble(); + if (Double.isNaN(x) || Double.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalError("expected condition: %s", this); + } + } + default: + throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this); + } + } + public Condition join(Condition other) { if (other == this) { return this; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java index a1d2661e71b..bc2627ebb5e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.common.cfg; -import java.util.Collections; -import java.util.List; - public abstract class AbstractBlockBase> { protected int id; @@ -34,7 +31,8 @@ public abstract class AbstractBlockBase> { protected T[] successors; private T dominator; - private List dominated; + private T firstDominated; + private T dominatedSibling; private int domNumber; private int maxChildDomNumber; @@ -97,19 +95,27 @@ public abstract class AbstractBlockBase> { this.domDepth = dominator.domDepth + 1; } + /** + * Level in the dominator tree starting with 0 for the start block. + */ public int getDominatorDepth() { return domDepth; } - public List getDominated() { - if (dominated == null) { - return Collections.emptyList(); - } - return dominated; + public T getFirstDominated() { + return this.firstDominated; } - public void setDominated(List blocks) { - dominated = blocks; + public void setFirstDominated(T block) { + this.firstDominated = block; + } + + public T getDominatedSibling() { + return this.dominatedSibling; + } + + public void setDominatedSibling(T block) { + this.dominatedSibling = block; } @Override @@ -158,4 +164,9 @@ public abstract class AbstractBlockBase> { public abstract double probability(); public abstract T getDominator(int distance); + + @Override + public int hashCode() { + return id; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java index ccc46e4e4e8..5b81652d5a2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java @@ -81,6 +81,8 @@ public interface AbstractControlFlowGraph> { return b; } else if (b == null) { return a; + } else if (a == b) { + return a; } else { int aDomDepth = a.getDominatorDepth(); int bDomDepth = b.getDominatorDepth(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java index ec9a55f4bca..cac5c9f7b33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java @@ -45,11 +45,22 @@ public class CFGVerifier { if (block.getDominator() != null) { assert block.getDominator().getId() < block.getId(); - assert block.getDominator().getDominated().contains(block); + + AbstractBlockBase domChild = block.getDominator().getFirstDominated(); + while (domChild != null) { + if (domChild == block) { + break; + } + domChild = domChild.getDominatedSibling(); + } + assert domChild != null : "dominators must contain block"; } - for (T dominated : block.getDominated()) { + + T dominated = block.getFirstDominated(); + while (dominated != null) { assert dominated.getId() > block.getId(); assert dominated.getDominator() == block; + dominated = dominated.getDominatedSibling(); } T postDominatorBlock = block.getPostdominator(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java index 41d884addd5..8b3048feec0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java @@ -105,4 +105,9 @@ public abstract class Loop> { } return false; } + + @Override + public int hashCode() { + return index + depth * 31; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java index 2cc96bcd43d..3327d9f1238 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.core.common.spi; +import org.graalvm.compiler.options.OptionValues; + import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ResolvedJavaField; @@ -32,6 +34,8 @@ public interface ConstantFieldProvider { public interface ConstantFieldTool { + OptionValues getOptions(); + JavaConstant readValue(); JavaConstant getReceiver(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java index 58890ea9db6..63f2bfb203f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.core.common.spi; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.ValueKindFactory; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java index ae40986bd5c..c6dfab4540a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.core.common.spi; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaType; @@ -39,7 +39,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider static class Options { @Option(help = "Determines whether to treat final fields with default values as constant.")// - public static final OptionValue TrustFinalDefaultFields = new OptionValue<>(true); + public static final OptionKey TrustFinalDefaultFields = new OptionKey<>(true); } protected JavaConstantFieldProvider(MetaAccessProvider metaAccess) { @@ -93,7 +93,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider @SuppressWarnings("unused") protected boolean isFinalFieldValueConstant(ResolvedJavaField field, JavaConstant value, ConstantFieldTool tool) { - return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue(); + return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue(tool.getOptions()); } @SuppressWarnings("unused") @@ -104,7 +104,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider if (isWellKnownImplicitStableField(field)) { return true; } - if (field == stringHashField) { + if (field.equals(stringHashField)) { return true; } return false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java index 9a4015476bf..a74c96ad17b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java @@ -48,4 +48,14 @@ public interface LIRKindTool { * Get the architecture specific kind pointer-sized integer kind. */ LIRKind getWordKind(); + + /** + * Get the platform specific kind used to represent compressed oops. + */ + LIRKind getNarrowOopKind(); + + /** + * Gets the platform specific kind used to represent compressed metaspace pointers. + */ + LIRKind getNarrowPointerKind(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java index 7debe2c12ea..a8cf097051f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java @@ -59,8 +59,8 @@ public abstract class AbstractPointerStamp extends Stamp { return result; } - @Override - public Stamp join(Stamp stamp) { + protected Stamp defaultPointerJoin(Stamp stamp) { + assert getClass() == stamp.getClass(); AbstractPointerStamp other = (AbstractPointerStamp) stamp; boolean joinNonNull = this.nonNull || other.nonNull; boolean joinAlwaysNull = this.alwaysNull || other.alwaysNull; @@ -89,6 +89,42 @@ public abstract class AbstractPointerStamp extends Stamp { return copyWith(false, false); } + public static Stamp pointerNonNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asNonNull(); + } + + public static Stamp pointerMaybeNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asMaybeNull(); + } + + public static Stamp pointerAlwaysNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asAlwaysNull(); + } + + public Stamp asNonNull() { + if (isEmpty()) { + return this; + } + return copyWith(true, false); + } + + public Stamp asMaybeNull() { + if (isEmpty()) { + return this; + } + return copyWith(false, false); + } + + public Stamp asAlwaysNull() { + if (isEmpty()) { + return this; + } + return copyWith(false, true); + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java index af71cb1964f..5bd75e637c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java @@ -27,11 +27,6 @@ import static jdk.vm.ci.meta.MetaUtil.getSimpleName; import java.util.Arrays; import java.util.Objects; import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add; @@ -52,6 +47,10 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Abs; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Neg; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Not; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt; +import org.graalvm.util.CollectionsUtil; + +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaKind; /** * Information about arithmetic operations. @@ -95,12 +94,6 @@ public final class ArithmeticOpTable { public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); - public ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, - BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, - IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { - this(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, Stream.of(floatConvert)); - } - public interface ArithmeticOpWrapper { UnaryOp wrapUnaryOp(UnaryOp op); @@ -147,14 +140,13 @@ public final class ArithmeticOpTable { IntegerConvertOp signExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getSignExtend()); IntegerConvertOp narrow = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getNarrow()); - Stream floatConvert = Stream.of(inner.floatConvert).filter(Objects::nonNull).map(wrapper::wrapFloatConvertOp); - + FloatConvertOp[] floatConvert = CollectionsUtil.filterAndMapToArray(inner.floatConvert, Objects::nonNull, wrapper::wrapFloatConvertOp, FloatConvertOp[]::new); return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, floatConvert); } - private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, + protected ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, - IntegerConvertOp signExtend, IntegerConvertOp narrow, Stream floatConvert) { + IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { this.neg = neg; this.add = add; this.sub = sub; @@ -174,7 +166,9 @@ public final class ArithmeticOpTable { this.signExtend = signExtend; this.narrow = narrow; this.floatConvert = new FloatConvertOp[FloatConvert.values().length]; - floatConvert.forEach(op -> this.floatConvert[op.getFloatConvert().ordinal()] = op); + for (FloatConvertOp op : floatConvert) { + this.floatConvert[op.getFloatConvert().ordinal()] = op; + } this.hash = Objects.hash(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow); } @@ -318,7 +312,7 @@ public final class ArithmeticOpTable { } public static String toString(Op... ops) { - return Arrays.asList(ops).stream().map(o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}").collect(Collectors.joining(",")); + return CollectionsUtil.mapAndJoin(ops, o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}", ","); } private boolean opsEquals(ArithmeticOpTable that) { @@ -742,6 +736,11 @@ public final class ArithmeticOpTable { protected Narrow() { super("Narrow"); } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + return null; + } } protected IntegerConvertOp(String op) { @@ -755,5 +754,10 @@ public final class ArithmeticOpTable { public IntegerConvertOp unwrap() { return this; } + + /** + * Computes the stamp of the input for the given output stamp. + */ + public abstract Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java index ee0979f6d16..cb3ee14aa91 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java @@ -46,7 +46,11 @@ public abstract class ArithmeticStamp extends Stamp { @Override public Stamp improveWith(Stamp other) { - return this.join(other); + if (this.isCompatible(other)) { + return this.join(other); + } + // Cannot improve, because stamps are not compatible. + return this; } @Override @@ -65,7 +69,7 @@ public abstract class ArithmeticStamp extends Stamp { if (!(obj instanceof ArithmeticStamp)) { return false; } - assert Objects.equals(ops, ((ArithmeticStamp) obj).ops); + assert Objects.equals(ops, ((ArithmeticStamp) obj).ops) : ops + " vs. " + ((ArithmeticStamp) obj).ops; return true; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java index c55efe65a00..602feebb411 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java @@ -154,6 +154,7 @@ public class FloatStamp extends PrimitiveStamp { return Double.isNaN(lowerBound); } + @Override public boolean isUnrestricted() { return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; } @@ -301,10 +302,6 @@ public class FloatStamp extends PrimitiveStamp { return null; } - public boolean isConstant() { - return (nonNaN && Double.compare(lowerBound, upperBound) == 0); - } - private static final ArithmeticOpTable OPS = new ArithmeticOpTable( new UnaryOp.Neg() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java index b142e2c6d32..f41e7a34012 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java @@ -58,6 +58,11 @@ public final class IllegalStamp extends Stamp { return this; } + @Override + public boolean isUnrestricted() { + return true; + } + @Override public Stamp empty() { return this; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java index c76198db83d..c9fb891f453 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java @@ -31,6 +31,7 @@ import java.nio.ByteBuffer; import java.util.Formatter; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp; @@ -54,41 +55,101 @@ import jdk.vm.ci.meta.SerializableConstant; * The description consists of (inclusive) lower and upper bounds and up (may be set) and down * (always set) bit-masks. */ -public class IntegerStamp extends PrimitiveStamp { +public final class IntegerStamp extends PrimitiveStamp { private final long lowerBound; private final long upperBound; private final long downMask; private final long upMask; - public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { + private IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { super(bits, OPS); + this.lowerBound = lowerBound; this.upperBound = upperBound; this.downMask = downMask; this.upMask = upMask; + assert lowerBound >= CodeUtil.minValue(bits) : this; assert upperBound <= CodeUtil.maxValue(bits) : this; assert (downMask & CodeUtil.mask(bits)) == downMask : this; assert (upMask & CodeUtil.mask(bits)) == upMask : this; } - public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { - long lowerBound; - long upperBound; - if (((upMask >>> (bits - 1)) & 1) == 0) { - lowerBound = downMask; - upperBound = upMask; - } else if (((downMask >>> (bits - 1)) & 1) == 1) { - lowerBound = downMask; - upperBound = upMask; + public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput) { + return create(bits, lowerBoundInput, upperBoundInput, 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput, long downMask, long upMask) { + assert (downMask & ~upMask) == 0 : String.format("\u21ca: %016x \u21c8: %016x", downMask, upMask); + + // Set lower bound, use masks to make it more precise + long minValue = minValueForMasks(bits, downMask, upMask); + long lowerBoundTmp = Math.max(lowerBoundInput, minValue); + + // Set upper bound, use masks to make it more precise + long maxValue = maxValueForMasks(bits, downMask, upMask); + long upperBoundTmp = Math.min(upperBoundInput, maxValue); + + // Assign masks now with the bounds in mind. + final long boundedDownMask; + final long boundedUpMask; + long defaultMask = CodeUtil.mask(bits); + if (lowerBoundTmp == upperBoundTmp) { + boundedDownMask = lowerBoundTmp; + boundedUpMask = lowerBoundTmp; + } else if (lowerBoundTmp >= 0) { + int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBoundTmp); + long differentBits = lowerBoundTmp ^ upperBoundTmp; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); + + boundedUpMask = upperBoundTmp | -1L >>> (upperBoundLeadingZeros + sameBitCount); + boundedDownMask = upperBoundTmp & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); } else { - lowerBound = downMask | (-1L << (bits - 1)); - upperBound = CodeUtil.maxValue(bits) & upMask; + if (upperBoundTmp >= 0) { + boundedUpMask = defaultMask; + boundedDownMask = 0; + } else { + int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBoundTmp); + long differentBits = lowerBoundTmp ^ upperBoundTmp; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); + + boundedUpMask = lowerBoundTmp | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); + boundedDownMask = lowerBoundTmp & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); + } } - lowerBound = CodeUtil.convert(lowerBound, bits, false); - upperBound = CodeUtil.convert(upperBound, bits, false); - return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); + + return new IntegerStamp(bits, lowerBoundTmp, upperBoundTmp, defaultMask & (downMask | boundedDownMask), defaultMask & upMask & boundedUpMask); + } + + static long significantBit(long bits, long value) { + return (value >>> (bits - 1)) & 1; + } + + static long minValueForMasks(int bits, long downMask, long upMask) { + if (significantBit(bits, upMask) == 0) { + // Value is always positive. Minimum value always positive. + assert significantBit(bits, downMask) == 0; + return downMask; + } else { + // Value can be positive or negative. Minimum value always negative. + return downMask | (-1L << (bits - 1)); + } + } + + static long maxValueForMasks(int bits, long downMask, long upMask) { + if (significantBit(bits, downMask) == 1) { + // Value is always negative. Maximum value always negative. + assert significantBit(bits, upMask) == 1; + return CodeUtil.signExtend(upMask, bits); + } else { + // Value can be positive or negative. Maximum value always positive. + return upMask & (CodeUtil.mask(bits) >>> 1); + } + } + + public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { + return new IntegerStamp(bits, minValueForMasks(bits, downMask, upMask), maxValueForMasks(bits, downMask, upMask), downMask, upMask); } @Override @@ -97,7 +158,7 @@ public class IntegerStamp extends PrimitiveStamp { } @Override - public Stamp empty() { + public IntegerStamp empty() { return new IntegerStamp(getBits(), CodeUtil.maxValue(getBits()), CodeUtil.minValue(getBits()), CodeUtil.mask(getBits()), 0); } @@ -193,6 +254,7 @@ public class IntegerStamp extends PrimitiveStamp { return upMask; } + @Override public boolean isUnrestricted() { return lowerBound == CodeUtil.minValue(getBits()) && upperBound == CodeUtil.maxValue(getBits()) && downMask == 0 && upMask == CodeUtil.mask(getBits()); } @@ -230,23 +292,27 @@ public class IntegerStamp extends PrimitiveStamp { StringBuilder str = new StringBuilder(); str.append('i'); str.append(getBits()); - if (lowerBound == upperBound) { - str.append(" [").append(lowerBound).append(']'); - } else if (lowerBound != CodeUtil.minValue(getBits()) || upperBound != CodeUtil.maxValue(getBits())) { - str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); - } - if (downMask != 0) { - str.append(" \u21ca"); - new Formatter(str).format("%016x", downMask); - } - if (upMask != CodeUtil.mask(getBits())) { - str.append(" \u21c8"); - new Formatter(str).format("%016x", upMask); + if (hasValues()) { + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != CodeUtil.minValue(getBits()) || upperBound != CodeUtil.maxValue(getBits())) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + if (downMask != 0) { + str.append(" \u21ca"); + new Formatter(str).format("%016x", downMask); + } + if (upMask != CodeUtil.mask(getBits())) { + str.append(" \u21c8"); + new Formatter(str).format("%016x", upMask); + } + } else { + str.append(""); } return str.toString(); } - private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { + private IntegerStamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { assert getBits() == other.getBits(); if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0 || (newUpMask == 0 && (newLowerBound > 0 || newUpperBound < 0))) { return empty(); @@ -255,7 +321,7 @@ public class IntegerStamp extends PrimitiveStamp { } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { return other; } else { - return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); + return IntegerStamp.create(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); } } @@ -269,17 +335,16 @@ public class IntegerStamp extends PrimitiveStamp { } @Override - public Stamp join(Stamp otherStamp) { + public IntegerStamp join(Stamp otherStamp) { if (otherStamp == this) { return this; } IntegerStamp other = (IntegerStamp) otherStamp; long newDownMask = downMask | other.downMask; - long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; + long newLowerBound = Math.max(lowerBound, other.lowerBound); long newUpperBound = Math.min(upperBound, other.upperBound); long newUpMask = upMask & other.upMask; - IntegerStamp limit = StampFactory.forInteger(getBits(), newLowerBound, newUpperBound); - return createStamp(other, newUpperBound, newLowerBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); + return createStamp(other, newUpperBound, newLowerBound, newDownMask, newUpMask); } @Override @@ -303,6 +368,24 @@ public class IntegerStamp extends PrimitiveStamp { return false; } + public long unsignedUpperBound() { + if (sameSignBounds()) { + return CodeUtil.zeroExtend(upperBound(), getBits()); + } + return NumUtil.maxValueUnsigned(getBits()); + } + + public long unsignedLowerBound() { + if (sameSignBounds()) { + return CodeUtil.zeroExtend(lowerBound(), getBits()); + } + return 0; + } + + private boolean sameSignBounds() { + return NumUtil.sameSign(lowerBound, upperBound); + } + @Override public int hashCode() { final int prime = 31; @@ -369,6 +452,13 @@ public class IntegerStamp extends PrimitiveStamp { return null; } + public static boolean addCanOverflow(IntegerStamp a, IntegerStamp b) { + assert a.getBits() == b.getBits(); + return addOverflowsPositively(a.upperBound(), b.upperBound(), a.getBits()) || + addOverflowsNegatively(a.lowerBound(), b.lowerBound(), a.getBits()); + + } + public static boolean addOverflowsPositively(long x, long y, int bits) { long result = x + y; if (bits == 64) { @@ -430,15 +520,59 @@ public class IntegerStamp extends PrimitiveStamp { } } + public static boolean multiplicationCanOverflow(IntegerStamp a, IntegerStamp b) { + // see IntegerStamp#foldStamp for details + assert a.getBits() == b.getBits(); + if (a.upMask() == 0) { + return false; + } else if (b.upMask() == 0) { + return false; + } + if (a.isUnrestricted()) { + return true; + } + if (b.isUnrestricted()) { + return true; + } + int bits = a.getBits(); + long minNegA = a.lowerBound(); + long maxNegA = Math.min(0, a.upperBound()); + long minPosA = Math.max(0, a.lowerBound()); + long maxPosA = a.upperBound(); + + long minNegB = b.lowerBound(); + long maxNegB = Math.min(0, b.upperBound()); + long minPosB = Math.max(0, b.lowerBound()); + long maxPosB = b.upperBound(); + + boolean mayOverflow = false; + if (a.canBePositive()) { + if (b.canBePositive()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, maxPosB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, minPosB, bits); + } + if (b.canBeNegative()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, maxNegB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, minNegB, bits); + + } + } + if (a.canBeNegative()) { + if (b.canBePositive()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, minPosB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, maxPosB, bits); + } + if (b.canBeNegative()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, minNegB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, maxNegB, bits); + } + } + return mayOverflow; + } + public static boolean subtractionCanOverflow(IntegerStamp x, IntegerStamp y) { assert x.getBits() == y.getBits(); - // Checkstyle: stop - long x_l = x.lowerBound(); - long x_h = x.upperBound(); - long y_l = y.lowerBound(); - long y_h = y.upperBound(); - // Checkstyle: resume - return subtractionOverflows(x_l, y_h, x.getBits()) || subtractionOverflows(x_h, y_l, x.getBits()); + return subtractionOverflows(x.lowerBound(), y.upperBound(), x.getBits()) || subtractionOverflows(x.upperBound(), y.lowerBound(), x.getBits()); } public static boolean subtractionOverflows(long x, long y, int bits) { @@ -618,7 +752,7 @@ public class IntegerStamp extends PrimitiveStamp { * upper bound after multiplication. * * For example if we consider two stamps a & b that both contain - * negative and positive values, the product of minN_a * minN_b + * negative and positive values, the product of minNegA * minNegB * (both the smallest negative value for each stamp) can only be the * highest positive number. The other candidates can be computed in * a similar fashion. Some of them can never be a new minimum or @@ -627,87 +761,86 @@ public class IntegerStamp extends PrimitiveStamp { * * @formatter:off * - * [x..........0..........y] - * ------------------------- - * [minN maxN minP maxP] - * where maxN = min(0,y) && minP = max(0,x) + * [x................0................y] + * ------------------------------------- + * [minNeg maxNeg minPos maxPos] + * + * where maxNeg = min(0,y) && minPos = max(0,x) * * - * |minN_a maxN_a minP_a maxP_a - * _______|________________________________ - * minN_b |MAX / : / MIN - * maxN_b | / MIN : MAX / - * |---------------+---------------- - * minP_b | / MAX : MIN / - * maxP_b |MIN / : / MAX + * |minNegA maxNegA minPosA maxPosA + * _______ |____________________________________ + * minNegB | MAX / : / MIN + * maxNegB | / MIN : MAX / + * |------------------+----------------- + * minPosB | / MAX : MIN / + * maxPosB | MIN / : / MAX * * @formatter:on */ // We materialize all factors here. If they are needed, the signs of // the stamp will ensure the correct value is used. - // Checkstyle: stop - long minN_a = a.lowerBound(); - long maxN_a = Math.min(0, a.upperBound()); - long minP_a = Math.max(0, a.lowerBound()); - long maxP_a = a.upperBound(); + long minNegA = a.lowerBound(); + long maxNegA = Math.min(0, a.upperBound()); + long minPosA = Math.max(0, a.lowerBound()); + long maxPosA = a.upperBound(); - long minN_b = b.lowerBound(); - long maxN_b = Math.min(0, b.upperBound()); - long minP_b = Math.max(0, b.lowerBound()); - long maxP_b = b.upperBound(); - // Checkstyle: resume + long minNegB = b.lowerBound(); + long maxNegB = Math.min(0, b.upperBound()); + long minPosB = Math.max(0, b.lowerBound()); + long maxPosB = b.upperBound(); // multiplication has shift semantics long newUpMask = ~CodeUtil.mask(Long.numberOfTrailingZeros(a.upMask) + Long.numberOfTrailingZeros(b.upMask)) & CodeUtil.mask(bits); if (a.canBePositive()) { if (b.canBePositive()) { - if (multiplicationOverflows(maxP_a, maxP_b, bits)) { + if (multiplicationOverflows(maxPosA, maxPosB, bits)) { return a.unrestricted(); } - long maxCandidate = maxP_a * maxP_b; - if (multiplicationOverflows(minP_a, minP_b, bits)) { + long maxCandidate = maxPosA * maxPosB; + if (multiplicationOverflows(minPosA, minPosB, bits)) { return a.unrestricted(); } - long minCandidate = minP_a * minP_b; + long minCandidate = minPosA * minPosB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } if (b.canBeNegative()) { - if (multiplicationOverflows(minP_a, maxN_b, bits)) { + if (multiplicationOverflows(minPosA, maxNegB, bits)) { return a.unrestricted(); } - long maxCandidate = minP_a * maxN_b; - if (multiplicationOverflows(maxP_a, minN_b, bits)) { + long maxCandidate = minPosA * maxNegB; + if (multiplicationOverflows(maxPosA, minNegB, bits)) { return a.unrestricted(); } - long minCandidate = maxP_a * minN_b; + long minCandidate = maxPosA * minNegB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } } if (a.canBeNegative()) { if (b.canBePositive()) { - if (multiplicationOverflows(maxN_a, minP_b, bits)) { + if (multiplicationOverflows(maxNegA, minPosB, bits)) { return a.unrestricted(); } - long maxCandidate = maxN_a * minP_b; - if (multiplicationOverflows(minN_a, maxP_b, bits)) { + long maxCandidate = maxNegA * minPosB; + if (multiplicationOverflows(minNegA, maxPosB, bits)) { return a.unrestricted(); } - long minCandidate = minN_a * maxP_b; + long minCandidate = minNegA * maxPosB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } if (b.canBeNegative()) { - if (multiplicationOverflows(minN_a, minN_b, bits)) { + if (multiplicationOverflows(minNegA, minNegB, bits)) { return a.unrestricted(); } - long maxCandidate = minN_a * minN_b; - if (multiplicationOverflows(maxN_a, maxN_b, bits)) { + long maxCandidate = minNegA * minNegB; + if (multiplicationOverflows(maxNegA, maxNegB, bits)) { return a.unrestricted(); } - long minCandidate = maxN_a * maxN_b; + long minCandidate = maxNegA * maxNegB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } @@ -1083,22 +1216,28 @@ public class IntegerStamp extends PrimitiveStamp { assert inputBits == stamp.getBits(); assert inputBits <= resultBits; - long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); - long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); - - if (stamp.lowerBound() < 0 && stamp.upperBound() >= 0) { - /* signed range including 0 and -1 */ - /* - * after sign extension, the whole range from 0 to MAX_INT is - * possible - */ - return IntegerStamp.stampForMask(resultBits, downMask, upMask); + if (inputBits == resultBits) { + return input; } - long lowerBound = CodeUtil.zeroExtend(stamp.lowerBound(), inputBits); - long upperBound = CodeUtil.zeroExtend(stamp.upperBound(), inputBits); + if (input.isEmpty()) { + return StampFactory.forInteger(resultBits).empty(); + } - return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask); + long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); + long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); + long lowerBound = stamp.unsignedLowerBound(); + long upperBound = stamp.unsignedUpperBound(); + return IntegerStamp.create(resultBits, lowerBound, upperBound, downMask, upMask); + } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + IntegerStamp stamp = (IntegerStamp) outStamp; + if (stamp.isEmpty()) { + return StampFactory.forInteger(inputBits).empty(); + } + return StampFactory.forUnsignedInteger(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask(), stamp.upMask()); } }, @@ -1122,6 +1261,13 @@ public class IntegerStamp extends PrimitiveStamp { return new IntegerStamp(resultBits, stamp.lowerBound(), stamp.upperBound(), downMask, upMask); } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + IntegerStamp stamp = (IntegerStamp) outStamp; + long mask = CodeUtil.mask(inputBits); + return StampFactory.forIntegerWithMask(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask() & mask, stamp.upMask() & mask); + } }, new IntegerConvertOp.Narrow() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java index c9df00104c4..d3c64e6d04e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java @@ -80,6 +80,14 @@ public class ObjectStamp extends AbstractObjectStamp { @Override public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { - return provider.readObjectConstant(base, displacement); + try { + return provider.readObjectConstant(base, displacement); + } catch (IllegalArgumentException e) { + /* + * It's possible that the base and displacement aren't valid together so simply return + * null. + */ + return null; + } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java index 4bd3e91bfcd..19e4c69fa25 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java @@ -54,7 +54,15 @@ public abstract class PrimitiveStamp extends ArithmeticStamp { @Override public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { - return provider.readPrimitiveConstant(getStackKind(), base, displacement, getBits()); + try { + return provider.readPrimitiveConstant(getStackKind(), base, displacement, getBits()); + } catch (IllegalArgumentException e) { + /* + * It's possible that the base and displacement aren't valid together so simply return + * null. + */ + return null; + } } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java index 0620856ec50..ab7c06363f3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java @@ -125,6 +125,13 @@ public abstract class Stamp { return !hasValues(); } + /** + * Tests whether this stamp represents all values of this kind. + */ + public boolean isUnrestricted() { + return this.equals(this.unrestricted()); + } + /** * If this stamp represents a single value, the methods returns this single value. It returns * null otherwise. @@ -138,6 +145,8 @@ public abstract class Stamp { /** * Read a value of this stamp from memory. + * + * @return the value read or null if the value can't be read for some reason. */ public abstract Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java index 7563067b584..2d94012cf75 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.core.common.type; +import static jdk.vm.ci.code.CodeUtil.signExtend; + +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.CodeUtil; @@ -36,28 +39,6 @@ import jdk.vm.ci.meta.Signature; public class StampFactory { - /* - * The marker stamp for node intrinsics must be its own class, so that it is never equal() to a - * regular ObjectStamp. - */ - static final class NodeIntrinsicStamp extends ObjectStamp { - protected static final Stamp SINGLETON = new NodeIntrinsicStamp(); - - private NodeIntrinsicStamp() { - super(null, false, false, false); - } - - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - @Override - public boolean equals(Object obj) { - return this == obj; - } - } - // JaCoCo Exclude private static final Stamp[] stampCache = new Stamp[JavaKind.values().length]; @@ -82,7 +63,7 @@ public class StampFactory { } else { mask = CodeUtil.mask(bits); } - setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); + setCache(kind, IntegerStamp.create(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); } private static void setFloatCache(JavaKind kind) { @@ -135,14 +116,6 @@ public class StampFactory { return VoidStamp.getInstance(); } - /** - * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an - * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. - */ - public static Stamp forNodeIntrinsic() { - return NodeIntrinsicStamp.SINGLETON; - } - public static Stamp intValue() { return forKind(JavaKind.Int); } @@ -156,7 +129,7 @@ public class StampFactory { } public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound, long downMask, long upMask) { - return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); + return IntegerStamp.create(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); } public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound) { @@ -176,46 +149,35 @@ public class StampFactory { */ public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, IntegerStamp maskStamp) { IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); - return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | maskStamp.downMask(), limit.upMask() & maskStamp.upMask()); + return IntegerStamp.create(bits, newLowerBound, newUpperBound, limit.downMask() | maskStamp.downMask(), limit.upMask() & maskStamp.upMask()); } public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, long newDownMask, long newUpMask) { IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); - return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); + return IntegerStamp.create(bits, newLowerBound, newUpperBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); } public static IntegerStamp forInteger(int bits) { - return new IntegerStamp(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits)); + return IntegerStamp.create(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp forUnsignedInteger(int bits, long unsignedLowerBound, long unsignedUpperBound) { + return forUnsignedInteger(bits, unsignedLowerBound, unsignedUpperBound, 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp forUnsignedInteger(int bits, long unsignedLowerBound, long unsignedUpperBound, long downMask, long upMask) { + long lowerBound = signExtend(unsignedLowerBound, bits); + long upperBound = signExtend(unsignedUpperBound, bits); + if (!NumUtil.sameSign(lowerBound, upperBound)) { + lowerBound = CodeUtil.minValue(bits); + upperBound = CodeUtil.maxValue(bits); + } + long mask = CodeUtil.mask(bits); + return IntegerStamp.create(bits, lowerBound, upperBound, downMask & mask, upMask & mask); } public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) { - long defaultMask = CodeUtil.mask(bits); - if (lowerBound == upperBound) { - return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); - } - final long downMask; - final long upMask; - if (lowerBound >= 0) { - int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); - - upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); - downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); - } else { - if (upperBound >= 0) { - upMask = defaultMask; - downMask = 0; - } else { - int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); - - upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); - downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); - } - } - return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); + return IntegerStamp.create(bits, lowerBound, upperBound, 0, CodeUtil.mask(bits)); } public static FloatStamp forFloat(JavaKind kind, double lowerBound, double upperBound, boolean nonNaN) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java index 7d3ad60eff4..b867c5ca245 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java @@ -45,6 +45,11 @@ public final class VoidStamp extends Stamp { return this; } + @Override + public boolean isUnrestricted() { + return true; + } + @Override public JavaKind getStackKind() { return JavaKind.Void; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java deleted file mode 100644 index e9a63ffaf86..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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; - -/** - * The {@code ArrayMap} class implements an efficient one-level map which is implemented as an - * array. Note that because of the one-level array inside, this data structure performs best when - * the range of integer keys is small and densely used. Note that the implementation can handle - * arbitrary intervals, including negative numbers, up to intervals of size 2^31 - 1. - */ -public class ArrayMap { - - private static final int INITIAL_SIZE = 5; // how big the initial array should be - private static final int EXTRA = 2; // how far on the left or right of a new element to grow - - Object[] map; - int low; - - /** - * Constructs a new {@code ArrayMap} with no initial assumptions. - */ - public ArrayMap() { - } - - /** - * Constructs a new {@code ArrayMap} that initially covers the specified interval. Note that - * this map will automatically expand if necessary later. - * - * @param low the low index, inclusive - * @param high the high index, exclusive - */ - public ArrayMap(int low, int high) { - this.low = low; - this.map = new Object[high - low + 1]; - } - - /** - * Puts a new value in the map at the specified index. - * - * @param i the index at which to store the value - * @param value the value to store at the specified index - */ - public void put(int i, T value) { - int index = i - low; - if (map == null) { - // no map yet - map = new Object[INITIAL_SIZE]; - low = index - 2; - map[INITIAL_SIZE / 2] = value; - } else if (index < 0) { - // grow backwards - growBackward(i, value); - } else if (index >= map.length) { - // grow forwards - growForward(i, value); - } else { - // no growth necessary - map[index] = value; - } - } - - /** - * Gets the value at the specified index in the map. - * - * @param i the index - * @return the value at the specified index; {@code null} if there is no value at the specified - * index, or if the index is out of the currently stored range - */ - public T get(int i) { - int index = i - low; - if (map == null || index < 0 || index >= map.length) { - return null; - } - Class type = null; - return Util.uncheckedCast(type, map[index]); - } - - public int length() { - return map.length; - } - - private void growBackward(int i, T value) { - int nlow = i - EXTRA; - Object[] nmap = new Object[low - nlow + map.length]; - System.arraycopy(map, 0, nmap, low - nlow, map.length); - map = nmap; - low = nlow; - map[i - low] = value; - } - - private void growForward(int i, T value) { - int nlen = i - low + 1 + EXTRA; - Object[] nmap = new Object[nlen]; - System.arraycopy(map, 0, nmap, 0, map.length); - map = nmap; - map[i - low] = value; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java index f97b1712df2..b0dc7fd691d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java @@ -23,8 +23,9 @@ package org.graalvm.compiler.core.common.util; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; /** * Utility class that allows the compiler to monitor compilations that take a very long time. @@ -34,80 +35,74 @@ public final class CompilationAlarm implements AutoCloseable { public static class Options { // @formatter:off @Option(help = "Time limit in seconds before a compilation expires (0 to disable the limit).", type = OptionType.Debug) - public static final OptionValue CompilationExpirationPeriod = new OptionValue<>(300); + public static final OptionKey CompilationExpirationPeriod = new OptionKey<>(300); // @formatter:on } - private CompilationAlarm() { - } - - private static boolean enabled() { - return Options.CompilationExpirationPeriod.getValue() > 0; + private CompilationAlarm(long expiration) { + this.expiration = expiration; } /** - * Thread local storage for compilation start timestamps. Everytime a compiler thread calls - * {@link #trackCompilationPeriod()} it will save the start timestamp of the compilation. + * Thread local storage for the active compilation alarm. */ - private static final ThreadLocal compilationStartedTimeStamps = new ThreadLocal<>(); + private static final ThreadLocal currentAlarm = new ThreadLocal<>(); - private static boolean compilationStarted() { - if (enabled()) { - Long start = compilationStartedTimeStamps.get(); - if (start == null) { - compilationStartedTimeStamps.set(System.currentTimeMillis()); - return true; - } - } - return false; - } + private static final CompilationAlarm NEVER_EXPIRES = new CompilationAlarm(0); - private static void compilationFinished() { - if (enabled()) { - assert compilationStartedTimeStamps.get() != null; - compilationStartedTimeStamps.set(null); - } + /** + * Gets the current compilation alarm. If there is no current alarm, a non-null value is + * returned that will always return {@code false} for {@link #hasExpired()}. + */ + public static CompilationAlarm current() { + CompilationAlarm alarm = currentAlarm.get(); + return alarm == null ? NEVER_EXPIRES : alarm; } /** - * Determines if the current compilation is expired. A compilation expires if it takes longer - * than {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}. + * Determines if this alarm has expired. A compilation expires if it takes longer than + * {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}. * * @return {@code true} if the current compilation already takes longer than * {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}, {@code false} * otherwise */ - public static boolean hasExpired() { - if (enabled()) { - Long start = compilationStartedTimeStamps.get(); - if (start != null) { - long time = System.currentTimeMillis(); - assert time >= start; - return time - start > Options.CompilationExpirationPeriod.getValue() * 1000; - } - } - return false; + public boolean hasExpired() { + return this != NEVER_EXPIRES && System.currentTimeMillis() > expiration; } @Override public void close() { - compilationFinished(); + if (this != NEVER_EXPIRES) { + currentAlarm.set(null); + } } - private static final CompilationAlarm INSTANCE = enabled() ? new CompilationAlarm() : null; + /** + * The time at which this alarm expires. + */ + private final long expiration; /** - * Gets an object that can be used in a try-with-resource statement to set an time limit based - * alarm for a compilation. + * Starts an alarm for setting a time limit on a compilation if there isn't already an active + * alarm and {@link CompilationAlarm.Options#CompilationExpirationPeriod}{@code > 0}. The + * returned value can be used in a try-with-resource statement to disable the alarm once the + * compilation is finished. * - * @return a {@link CompilationAlarm} instance if there is no current alarm for the calling - * thread otherwise {@code null} + * @return a {@link CompilationAlarm} if there was no current alarm for the calling thread + * before this call otherwise {@code null} */ - public static CompilationAlarm trackCompilationPeriod() { - if (compilationStarted()) { - return INSTANCE; + public static CompilationAlarm trackCompilationPeriod(OptionValues options) { + int period = Options.CompilationExpirationPeriod.getValue(options); + if (period > 0) { + CompilationAlarm current = currentAlarm.get(); + if (current == null) { + long expiration = System.currentTimeMillis() + period * 1000; + current = new CompilationAlarm(expiration); + currentAlarm.set(current); + return current; + } } return null; } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java index 736754620cc..09a840b5ca8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java @@ -23,10 +23,10 @@ package org.graalvm.compiler.core.common.util; import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; import java.util.List; -import java.util.Map; + +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Creates an array of T objects order by the occurrence frequency of each object. The most @@ -49,24 +49,24 @@ public class FrequencyEncoder { } } - protected final Map> map; + protected final EconomicMap> map; protected boolean containsNull; /** * Creates an encoder that uses object identity. */ public static FrequencyEncoder createIdentityEncoder() { - return new FrequencyEncoder<>(new IdentityHashMap<>()); + return new FrequencyEncoder<>(EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE)); } /** * Creates an encoder that uses {@link Object#equals(Object) object equality}. */ public static FrequencyEncoder createEqualityEncoder() { - return new FrequencyEncoder<>(new HashMap<>()); + return new FrequencyEncoder<>(EconomicMap.create(Equivalence.DEFAULT)); } - protected FrequencyEncoder(Map> map) { + protected FrequencyEncoder(EconomicMap> map) { this.map = map; } @@ -91,7 +91,7 @@ public class FrequencyEncoder { * Returns the index of an object in the array. The object must have been * {@link #addObject(Object) added} before. */ - public int getIndex(Object object) { + public int getIndex(T object) { if (object == null) { assert containsNull; return 0; @@ -114,7 +114,10 @@ public class FrequencyEncoder { */ public T[] encodeAll(T[] allObjects) { assert allObjects.length == getLength(); - List> sortedEntries = new ArrayList<>(map.values()); + List> sortedEntries = new ArrayList<>(allObjects.length); + for (Entry value : map.getValues()) { + sortedEntries.add(value); + } sortedEntries.sort((e1, e2) -> -Integer.compare(e1.frequency, e2.frequency)); int offset = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java index 6f58e683bc6..d13d9fecf10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java @@ -31,6 +31,8 @@ import java.util.Arrays; */ public final class IntList { + private static final int[] EMPTY_INT_ARRAY = new int[0]; + private int[] array; private int size; @@ -80,9 +82,13 @@ public final class IntList { */ public static IntList copy(IntList other, int startIndex, int length, int initialCapacity) { assert initialCapacity >= length : "initialCapacity < length"; - int[] array = new int[initialCapacity]; - System.arraycopy(other.array, startIndex, array, 0, length); - return new IntList(array, length); + if (initialCapacity == 0) { + return new IntList(EMPTY_INT_ARRAY, 0); + } else { + int[] array = new int[initialCapacity]; + System.arraycopy(other.array, startIndex, array, 0, length); + return new IntList(array, length); + } } public int size() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java index 86e1bac530a..2c38dfdeba0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.core.common.util; -import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERSION; +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 @@ -41,11 +43,19 @@ import java.lang.reflect.Modifier; */ public final class ModuleAPI { - private ModuleAPI(Method method) { - this.method = method; + public ModuleAPI(Class declaringClass, String name, Class... parameterTypes) { + try { + this.method = declaringClass.getMethod(name, parameterTypes); + } catch (Exception e) { + throw new GraalError(e); + } } - private final Method method; + public final Method method; + + public Class getReturnType() { + return method.getReturnType(); + } /** * {@code Class.getModule()}. @@ -57,16 +67,6 @@ public final class ModuleAPI { */ public static final ModuleAPI getResourceAsStream; - /** - * {@code java.lang.Module.canRead(Module)}. - */ - public static final ModuleAPI canRead; - - /** - * {@code java.lang.Module.isExported(String)}. - */ - public static final ModuleAPI isExported; - /** * {@code java.lang.Module.isExported(String, Module)}. */ @@ -82,7 +82,7 @@ public final class ModuleAPI { try { return (T) method.invoke(null, args); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new InternalError(e); + throw new GraalError(e); } } @@ -96,35 +96,31 @@ public final class ModuleAPI { try { return (T) method.invoke(receiver, args); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new InternalError(e); + throw new GraalError(e); } } - private void checkAvailability() throws InternalError { + private void checkAvailability() throws GraalError { if (method == null) { - throw new InternalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION); + throw new GraalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION); } } static { if (JAVA_SPECIFICATION_VERSION >= 9) { - try { - getModule = new ModuleAPI(Class.class.getMethod("getModule")); - Class moduleClass = getModule.method.getReturnType(); - getResourceAsStream = new ModuleAPI(moduleClass.getMethod("getResourceAsStream", String.class)); - canRead = new ModuleAPI(moduleClass.getMethod("canRead", moduleClass)); - isExported = new ModuleAPI(moduleClass.getMethod("isExported", String.class)); - isExportedTo = new ModuleAPI(moduleClass.getMethod("isExported", String.class, moduleClass)); - } catch (NoSuchMethodException | SecurityException e) { - throw new InternalError(e); - } + 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(null); + ModuleAPI unavailable = new ModuleAPI(); getModule = unavailable; getResourceAsStream = unavailable; - canRead = unavailable; - isExported = unavailable; isExportedTo = unavailable; } } + + private ModuleAPI() { + method = null; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java new file mode 100644 index 00000000000..d5fcd1fd12d --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java @@ -0,0 +1,58 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 java.util.AbstractList; +import java.util.List; +import java.util.RandomAccess; + +/** + * A {@code ReversedList} is a view on an other list with the elements in reverse order. + * + * This implementation is made for {@link RandomAccess} lists. + */ +public class ReversedList extends AbstractList implements RandomAccess { + private final List original; + + public ReversedList(List original) { + assert original instanceof RandomAccess; + this.original = original; + } + + @Override + public T get(int index) { + return original.get(original.size() - index - 1); + } + + @Override + public int size() { + return original.size(); + } + + /** + * Creates a list that is a view on {@code list} in reverse order. + */ + public static ReversedList reversed(List list) { + return new ReversedList<>(list); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java index 4e29d619daa..ef3669b0673 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.core.common.util; -import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; - -import java.util.Collection; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; import java.util.List; import org.graalvm.compiler.debug.TTY; @@ -39,25 +39,6 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class Util { - 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(); - - /** - * Determines if the Java runtime is version 8 or earlier. - */ - public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8; - /** * Statically cast an object to an arbitrary Object type. Dynamically checked. */ @@ -74,29 +55,6 @@ public class Util { return (T) object; } - public interface Stringify { - String apply(Object o); - } - - public static String join(Collection c, String sep) { - return join(c, sep, "", "", null); - } - - public static String join(Collection c, String sep, String prefix, String suffix, Stringify stringify) { - StringBuilder buf = new StringBuilder(prefix); - boolean first = true; - for (Object e : c) { - if (!first) { - buf.append(sep); - } else { - first = false; - } - buf.append(stringify != null ? stringify.apply(e) : String.valueOf(e)); - } - buf.append(suffix); - return buf.toString(); - } - /** * Sets the element at a given position of a list and ensures that this position exists. If the * list is current shorter than the position, intermediate positions are filled with a given @@ -191,25 +149,39 @@ public class Util { * Print a HotSpot-style inlining message to the console. */ public static void printInlining(final ResolvedJavaMethod method, final int bci, final int inliningDepth, final boolean success, final String msg, final Object... args) { - if (HotSpotPrintInlining.getValue()) { - StringBuilder sb = new StringBuilder(); - // 1234567 - sb.append(" "); // print timestamp - // 1234 - sb.append(" "); // print compilation number - // % s ! b n - sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); - sb.append(" "); // more indent - sb.append(" "); // initial inlining indent - for (int i = 0; i < inliningDepth; i++) { - sb.append(" "); - } - sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); - TTY.println(sb.toString()); + StringBuilder sb = new StringBuilder(); + // 1234567 + sb.append(" "); // print timestamp + // 1234 + sb.append(" "); // print compilation number + // % s ! b n + sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); + sb.append(" "); // more indent + sb.append(" "); // initial inlining indent + for (int i = 0; i < inliningDepth; i++) { + sb.append(" "); } + sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); + TTY.println(sb.toString()); } private static String methodName(ResolvedJavaMethod method) { return method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)"; } + + /** + * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code field} with the value + * {@code flag}. + */ + public static void setAccessible(Field field, boolean flag) { + field.setAccessible(flag); + } + + /** + * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code executable} with the value + * {@code flag}. + */ + public static void setAccessible(Executable executable, boolean flag) { + executable.setAccessible(flag); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java index 5129a503b7e..7351a71116d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java @@ -27,12 +27,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -74,6 +70,9 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; /** * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is @@ -206,13 +205,13 @@ public class MatchProcessor extends AbstractProcessor { name = next(); } originatingElements.addAll(type.originatingElements); - requiredPackages.add(type.nodePackage); } else if (Character.isLowerCase(peek("name").charAt(0))) { name = next(); type = valueType; } else { throw new RuleParseError("Unexpected token \"%s\" when looking for name or node type", peek(null)); } + requiredPackages.add(type.nodePackage); if (name != null) { if (!capturedNames.contains(name)) { capturedNames.add(name); @@ -234,7 +233,7 @@ public class MatchProcessor extends AbstractProcessor { /** * Recursively accumulate any required Position declarations. */ - void generatePositionDeclarations(Set declarations) { + void generatePositionDeclarations(EconomicSet declarations) { matchDescriptor.generatePositionDeclarations(declarations); } @@ -366,7 +365,7 @@ public class MatchProcessor extends AbstractProcessor { /** * The types which are know for purpose of parsing MatchRule expressions. */ - Map knownTypes = new HashMap<>(); + EconomicMap knownTypes = EconomicMap.create(Equivalence.DEFAULT); private TypeDescriptor valueType; @@ -407,7 +406,7 @@ public class MatchProcessor extends AbstractProcessor { } } - public void generatePositionDeclarations(Set declarations) { + public void generatePositionDeclarations(EconomicSet declarations) { if (inputs.length == 0) { return; } @@ -532,7 +531,7 @@ public class MatchProcessor extends AbstractProcessor { out.println(); // Generate declarations for the wrapper class to invoke the code generation methods. - for (MethodInvokerItem invoker : info.invokers.values()) { + for (MethodInvokerItem invoker : info.invokers.getValues()) { StringBuilder args = new StringBuilder(); StringBuilder types = new StringBuilder(); int count = invoker.fields.size(); @@ -663,14 +662,14 @@ public class MatchProcessor extends AbstractProcessor { final TypeElement topDeclaringType; final List matchRules = new ArrayList<>(); - private final Set originatingElements = new HashSet<>(); - public Set positionDeclarations = new LinkedHashSet<>(); + private final EconomicSet originatingElements = EconomicSet.create(Equivalence.DEFAULT); + public EconomicSet positionDeclarations = EconomicSet.create(Equivalence.DEFAULT); /** * The mapping between elements with MatchRules and the wrapper class used invoke the code * generation after the match. */ - Map invokers = new LinkedHashMap<>(); + EconomicMap invokers = EconomicMap.create(Equivalence.DEFAULT); /** * The set of packages which must be imported to refer the classes mention in matchRules. @@ -728,7 +727,7 @@ public class MatchProcessor extends AbstractProcessor { TypeMirror valueTypeMirror = processingEnv.getElementUtils().getTypeElement(ValueNode.class.getName()).asType(); valueType = new TypeDescriptor(valueTypeMirror, "Value", ValueNode.class.getSimpleName(), ValueNode.class.getPackage().getName(), new String[0], false, false); - Map map = new LinkedHashMap<>(); + EconomicMap map = EconomicMap.create(Equivalence.DEFAULT); for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) { currentElement = element; @@ -740,7 +739,7 @@ public class MatchProcessor extends AbstractProcessor { } currentElement = null; - for (MatchRuleDescriptor info : map.values()) { + for (MatchRuleDescriptor info : map.getValues()) { createFiles(info); } @@ -834,7 +833,7 @@ public class MatchProcessor extends AbstractProcessor { declareType(nodeClassMirror, shortName, nodeClass, nodePackage, matchable.inputs(), matchable.commutative(), matchable.shareable(), element); } - private void processMatchRule(Map map, Element element, AnnotationMirror mirror) { + private void processMatchRule(EconomicMap map, Element element, AnnotationMirror mirror) { if (!processedMatchRule.contains(element)) { try { processedMatchRule.add(element); @@ -961,7 +960,7 @@ public class MatchProcessor extends AbstractProcessor { Element enclosing = method.getEnclosingElement(); String declaringClass = ""; String separator = ""; - Set originatingElementsList = info.originatingElements; + EconomicSet originatingElementsList = info.originatingElements; originatingElementsList.add(method); while (enclosing != null) { if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java index e0f57456f04..b1171dba201 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java @@ -22,23 +22,24 @@ */ package org.graalvm.compiler.core.sparc.test; -import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; +import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; import static org.junit.Assume.assumeTrue; -import jdk.vm.ci.sparc.SPARC; import org.junit.Before; import org.junit.Test; import org.graalvm.compiler.core.test.backend.AllocatorTest; +import jdk.vm.ci.sparc.SPARC; + public class SPARCAllocatorTest extends AllocatorTest { @Before public void checkSPARC() { assumeTrue("skipping SPARC specific test", getTarget().arch instanceof SPARC); - assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue() == null); - assumeTrue("TraceRA is set -> skip", !TraceRA.getValue()); + assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); + assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); } @Test @@ -47,7 +48,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test1snippet(long x) { - return x + 5; + return x + 41; } @Test @@ -56,7 +57,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test2snippet(long x) { - return x * 5; + return x * 41; } @Test @@ -65,7 +66,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test3snippet(long x) { - return x / 3 + x % 3; + return x / 41 + x % 41; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java index 5edf7793eb5..9cee4a471e6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -113,12 +113,8 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { @Override public Variable emitBitCount(Value operand) { Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD)); - Value usedOperand = operand; - if (operand.getPlatformKind() == SPARCKind.WORD) { // Zero extend - usedOperand = getLIRGen().newVariable(operand.getValueKind()); - getLIRGen().append(new SPARCOP3Op(Op3s.Srl, operand, SPARC.g0.asValue(), usedOperand)); - } - getLIRGen().append(new SPARCOP3Op(Op3s.Popc, SPARC.g0.asValue(), usedOperand, result)); + AllocatableValue usedOperand = getLIRGen().asAllocatable(emitZeroExtend(operand)); + getLIRGen().append(new SPARCOP3Op(Op3s.Popc, g0.asValue(), usedOperand, result)); return result; } @@ -141,9 +137,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } @Override - public Value emitMathAbs(Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - SPARCKind kind = (SPARCKind) input.getPlatformKind(); + public Value emitMathAbs(Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + SPARCKind kind = (SPARCKind) inputValue.getPlatformKind(); Opfs opf; switch (kind) { case SINGLE: @@ -155,14 +151,14 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere("Input kind: " + kind); } - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } @Override - public Value emitMathSqrt(Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - SPARCKind kind = (SPARCKind) input.getPlatformKind(); + public Value emitMathSqrt(Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + SPARCKind kind = (SPARCKind) inputValue.getPlatformKind(); Opfs opf; switch (kind) { case SINGLE: @@ -174,7 +170,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere("Input kind: " + kind); } - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } @@ -193,15 +189,15 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { return emitUnary(Xnor, input); } - private Variable emitUnary(Opfs opf, Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + private Variable emitUnary(Opfs opf, Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } private Variable emitUnary(Op3s op3, Value input) { Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(SPARCOP3Op.newUnary(op3, input, result)); + getLIRGen().append(SPARCOP3Op.newUnary(op3, getLIRGen().loadSimm13(input), result)); return result; } @@ -211,11 +207,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { private Variable emitBinary(ValueKind resultKind, Opfs opf, Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(resultKind); - if (opf.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { - getLIRGen().append(new SPARCOPFOp(opf, b, a, result, state)); - } else { - getLIRGen().append(new SPARCOPFOp(opf, a, b, result, state)); - } + getLIRGen().append(new SPARCOPFOp(opf, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b), result, state)); return result; } @@ -230,9 +222,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { private Variable emitBinary(ValueKind resultKind, Op3s op3, Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(resultKind); if (op3.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { - getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), a, result, state)); + getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), getLIRGen().loadSimm13(a), result, state)); } else { - getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), b, result, state)); + getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), getLIRGen().loadSimm13(b), result, state)); } return result; } @@ -278,7 +270,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } return result; } else { - return emitBinary(resultKind, setFlags ? Op3s.Mulscc : Op3s.Mulx, a, b); + return emitBinary(resultKind, Op3s.Mulx, a, b); } } else { boolean isDouble = a.getPlatformKind().equals(DOUBLE); @@ -306,9 +298,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { public Value emitUMulHigh(Value a, Value b) { switch (((SPARCKind) a.getPlatformKind())) { case WORD: - Value aExtended = emitBinary(LIRKind.combine(a), Srl, a, 0); - Value bExtended = emitBinary(LIRKind.combine(b), Srl, b, 0); - Value result = emitBinary(LIRKind.combine(a, b), Mulx, aExtended, bExtended); + Value result = emitBinary(LIRKind.combine(a, b), Mulx, emitZeroExtend(a), emitZeroExtend(b)); return emitBinary(LIRKind.combine(a, b), Srax, result, WORD.getSizeInBits()); case XWORD: return emitBinary(LIRKind.combine(a, b), UMulxhi, a, b); @@ -327,17 +317,13 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { @Override public Value emitDiv(Value a, Value b, LIRFrameState state) { LIRKind resultKind = LIRKind.combine(a, b); - PlatformKind aKind = a.getPlatformKind(); - PlatformKind bKind = b.getPlatformKind(); if (isJavaConstant(b) && asJavaConstant(b).isDefaultForKind()) { // Div by zero Value zero = SPARC.g0.asValue(LIRKind.value(SPARCKind.WORD)); return emitBinary(resultKind, Op3s.Sdivx, zero, zero, state); - } else if (isNumericInteger(aKind)) { - Value fixedA = emitSignExtend(a, aKind.getSizeInBytes() * 8, 64); - Value fixedB = emitSignExtend(b, bKind.getSizeInBytes() * 8, 64); - return emitBinary(resultKind, Op3s.Sdivx, fixedA, fixedB, state); + } else if (isNumericInteger(a.getPlatformKind())) { + return emitBinary(resultKind, Op3s.Sdivx, emitSignExtend(a), emitSignExtend(b), state); } else { - boolean isDouble = a.getPlatformKind().equals(DOUBLE); + boolean isDouble = a.getPlatformKind() == DOUBLE; return emitBinary(resultKind, isDouble ? Opfs.Fdivd : Opfs.Fdivs, a, b, state); } } @@ -345,24 +331,21 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { @Override public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(LIRKind.combine(a, b)); - Value aLoaded; Variable q1; // Intermediate values Variable q2; - SPARCKind aKind = (SPARCKind) a.getPlatformKind(); - switch (aKind) { + switch ((SPARCKind) a.getPlatformKind()) { case WORD: // Sign extend a and b - Variable as = emitBinary(result.getValueKind(), Sra, a, g0.asValue(LIRKind.value(WORD))); - Variable bs = emitBinary(result.getValueKind(), Sra, b, g0.asValue(LIRKind.value(WORD))); + Value as = emitSignExtend(a); + Value bs = emitSignExtend(b); q1 = emitBinary(as.getValueKind(), Sdivx, as, bs, state); - q2 = emitBinary(q1.getValueKind(), Mulx, q1, bs); + q2 = emitBinary(as.getValueKind(), Mulx, q1, bs); result = emitSub(as, q2, false); break; case XWORD: - aLoaded = getLIRGen().load(a); // Reuse the loaded value - q1 = emitBinary(result.getValueKind(), Sdivx, aLoaded, b, state); + q1 = emitBinary(result.getValueKind(), Sdivx, a, b, state); q2 = emitBinary(result.getValueKind(), Mulx, q1, b); - result = emitSub(aLoaded, q2, false); + result = emitSub(a, q2, false); break; case SINGLE: ForeignCallLinkage fremCall = getLIRGen().getForeignCalls().lookupForeignCall(ARITHMETIC_FREM); @@ -394,26 +377,14 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere(); } - getLIRGen().append(new RemOp(opcode, result, getLIRGen().load(a), getLIRGen().load(b), scratch1, scratch2, state)); + getLIRGen().append(new RemOp(opcode, result, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b), scratch1, scratch2, state)); return result; } @Override public Value emitUDiv(Value a, Value b, LIRFrameState state) { - Value actualA = a; - Value actualB = b; - switch (((SPARCKind) a.getPlatformKind())) { - case WORD: - actualA = emitZeroExtend(actualA, 32, 64); - actualB = emitZeroExtend(actualB, 32, 64); - break; - case XWORD: - break; - default: - throw GraalError.shouldNotReachHere(); - } - return emitBinary(LIRKind.combine(actualA, actualB), Udivx, actualA, actualB, state); + return emitBinary(LIRKind.combine(a, b), Udivx, emitZeroExtend(a), emitZeroExtend(b), state); } @Override @@ -495,78 +466,78 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } @Override - public Value emitFloatConvert(FloatConvert op, Value inputVal) { - AllocatableValue input = getLIRGen().asAllocatable(inputVal); - Value result; + public Value emitFloatConvert(FloatConvert op, Value inputValue) { + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputValue); + AllocatableValue result; switch (op) { case D2F: - result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(SINGLE)); - getLIRGen().append(new SPARCOPFOp(Fdtos, inputVal, result)); + result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(SINGLE)); + getLIRGen().append(new SPARCOPFOp(Fdtos, inputAllocatable, result)); break; case F2D: - result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(DOUBLE)); - getLIRGen().append(new SPARCOPFOp(Fstod, inputVal, result)); + result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(DOUBLE)); + getLIRGen().append(new SPARCOPFOp(Fstod, inputAllocatable, result)); break; case I2F: { - AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); + AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); result = getLIRGen().newVariable(intEncodedFloatReg.getValueKind()); - moveBetweenFpGp(intEncodedFloatReg, input); + moveBetweenFpGp(intEncodedFloatReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Fitos, intEncodedFloatReg, result)); break; } case I2D: { // Unfortunately we must do int -> float -> double because fitod has float // and double encoding in one instruction - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - result = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - moveBetweenFpGp(convertedFloatReg, input); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + result = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + moveBetweenFpGp(convertedFloatReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Fitod, convertedFloatReg, result)); break; } case L2D: { - AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - moveBetweenFpGp(longEncodedDoubleReg, input); + AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + moveBetweenFpGp(longEncodedDoubleReg, inputAllocatable); AllocatableValue convertedDoubleReg = getLIRGen().newVariable(longEncodedDoubleReg.getValueKind()); getLIRGen().append(new SPARCOPFOp(Fxtod, longEncodedDoubleReg, convertedDoubleReg)); result = convertedDoubleReg; break; } case D2I: { - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, input, convertedFloatReg)); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, inputAllocatable, convertedFloatReg)); AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); moveBetweenFpGp(convertedIntReg, convertedFloatReg); result = convertedIntReg; break; } case F2L: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, input, convertedDoubleReg)); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, inputAllocatable, convertedDoubleReg)); AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); moveBetweenFpGp(convertedLongReg, convertedDoubleReg); result = convertedLongReg; break; } case F2I: { - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, input, convertedFloatReg)); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, inputAllocatable, convertedFloatReg)); AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); moveBetweenFpGp(convertedIntReg, convertedFloatReg); result = convertedIntReg; break; } case D2L: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, input, convertedDoubleReg)); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, inputAllocatable, convertedDoubleReg)); AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); moveBetweenFpGp(convertedLongReg, convertedDoubleReg); result = convertedLongReg; break; } case L2F: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - result = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - moveBetweenFpGp(convertedDoubleReg, input); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + result = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + moveBetweenFpGp(convertedDoubleReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Opfs.Fxtos, convertedDoubleReg, result)); break; } @@ -604,15 +575,19 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } } + private Value emitSignExtend(Value inputValue) { + int inputBits = inputValue.getPlatformKind().getSizeInBytes() * 8; + return emitNarrow(emitSignExtend(inputValue, inputBits, XWORD.getSizeInBits()), inputBits); + } + @Override public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= XWORD.getSizeInBits(); LIRKind shiftKind = LIRKind.value(WORD); LIRKind resultKind = LIRKind.combine(inputVal).changeType(toBits > 32 ? XWORD : WORD); - Value result; int shiftCount = XWORD.getSizeInBits() - fromBits; if (fromBits == toBits) { - result = inputVal; + return inputVal; } else if (isJavaConstant(inputVal)) { JavaConstant javaConstant = asJavaConstant(inputVal); long constant; @@ -622,30 +597,38 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { constant = javaConstant.asLong(); } return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount)); - } else if (fromBits == WORD.getSizeInBits() && toBits == XWORD.getSizeInBits()) { - result = getLIRGen().newVariable(resultKind); - getLIRGen().append(new SPARCOP3Op(Sra, inputVal, SPARC.g0.asValue(LIRKind.value(WORD)), result)); } else { - Variable tmp = getLIRGen().newVariable(resultKind.changeType(XWORD)); - result = getLIRGen().newVariable(resultKind); - getLIRGen().append(new SPARCOP3Op(Sllx, inputVal, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp)); - getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result)); + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputVal); + Variable result = getLIRGen().newVariable(resultKind); + if (fromBits == WORD.getSizeInBits() && toBits == XWORD.getSizeInBits()) { + getLIRGen().append(new SPARCOP3Op(Sra, inputAllocatable, g0.asValue(LIRKind.value(WORD)), result)); + } else { + Variable tmp = getLIRGen().newVariable(resultKind.changeType(XWORD)); + getLIRGen().append(new SPARCOP3Op(Sllx, inputAllocatable, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp)); + getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result)); + } + return result; } - return result; + } + + private Value emitZeroExtend(Value inputValue) { + int inputBits = inputValue.getPlatformKind().getSizeInBytes() * 8; + return emitNarrow(emitZeroExtend(inputValue, inputBits, XWORD.getSizeInBits()), inputBits); } @Override - public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { + public Value emitZeroExtend(Value inputValue, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { - return inputVal; + return inputValue; } - Variable result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(toBits > WORD.getSizeInBits() ? XWORD : WORD)); + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(toBits > WORD.getSizeInBits() ? XWORD : WORD)); + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputValue); if (fromBits == 32) { - getLIRGen().append(new SPARCOP3Op(Srl, inputVal, g0.asValue(), result)); + getLIRGen().append(new SPARCOP3Op(Srl, inputAllocatable, g0.asValue(), result)); } else { Value mask = getLIRGen().emitConstant(LIRKind.value(XWORD), forLong(mask(fromBits))); - getLIRGen().append(new SPARCOP3Op(And, inputVal, mask, result)); + getLIRGen().append(new SPARCOP3Op(And, inputAllocatable, mask, result)); } return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java index 0716b556974..abdef18c51e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java @@ -67,4 +67,19 @@ public class SPARCImmediateAddressNode extends AddressNode implements LIRLowerab gen.setResult(this, new SPARCImmediateAddressValue(kind, baseValue, displacement)); } + + @Override + public ValueNode getBase() { + return base; + } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } + + @Override + public ValueNode getIndex() { + return null; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java index 06c5725369e..3fee3e82ea1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java @@ -65,6 +65,7 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable gen.setResult(this, new SPARCIndexedAddressValue(kind, baseValue, indexValue)); } + @Override public ValueNode getBase() { return base; } @@ -74,6 +75,7 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -82,4 +84,9 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable updateUsages(this.index, index); this.index = index; } + + @Override + public long getMaxConstantDisplacement() { + return Long.MAX_VALUE; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java index 0023a12738c..95f3e5c58c5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -194,16 +194,16 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public void emitCompareBranch(PlatformKind cmpKind, Value x, Value y, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { - Value left; + AllocatableValue left; Value right; Condition actualCondition; if (isJavaConstant(x)) { left = load(y); - right = loadNonConst(x); + right = loadSimm13(x); actualCondition = cond.mirror(); } else { left = load(x); - right = loadNonConst(y); + right = loadSimm13(y); actualCondition = cond; } SPARCKind actualCmpKind = (SPARCKind) cmpKind; @@ -234,9 +234,9 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { private void emitIntegerTest(Value a, Value b) { assert ((SPARCKind) a.getPlatformKind()).isInteger(); if (LIRValueUtil.isVariable(b)) { - append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(b), loadNonConst(a))); + append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(b), loadSimm13(a))); } else { - append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(a), loadNonConst(b))); + append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(a), loadSimm13(b))); } } @@ -250,6 +250,23 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { return load(value); } + public Value loadSimm13(Value value) { + if (isJavaConstant(value)) { + JavaConstant c = asJavaConstant(value); + if (c.isNull() || SPARCAssembler.isSimm13(c)) { + return value; + } + } + return load(value); + } + + @Override + public Value loadNonConst(Value value) { + // SPARC does not support a proper way of loadNonConst. Please use the appropriate + // loadSimm11 or loadSimm13 variants. + throw GraalError.shouldNotReachHere("This operation is not available for SPARC."); + } + @Override public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { // Emit compare @@ -304,24 +321,24 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { private boolean emitIntegerCompare(SPARCKind cmpKind, Value a, Value b) { boolean mirrored; assert cmpKind.isInteger(); - Value left; + AllocatableValue left; Value right; if (LIRValueUtil.isVariable(b)) { left = load(b); - right = loadNonConst(a); + right = loadSimm13(a); mirrored = true; } else { left = load(a); - right = loadNonConst(b); + right = loadSimm13(b); mirrored = false; } int compareBytes = cmpKind.getSizeInBytes(); // SPARC compares 32 or 64 bits if (compareBytes < left.getPlatformKind().getSizeInBytes()) { - left = arithmeticLIRGen.emitSignExtend(left, compareBytes * 8, XWORD.getSizeInBytes() * 8); + left = asAllocatable(arithmeticLIRGen.emitSignExtend(left, cmpKind.getSizeInBits(), XWORD.getSizeInBits())); } if (compareBytes < right.getPlatformKind().getSizeInBytes()) { - right = arithmeticLIRGen.emitSignExtend(right, compareBytes * 8, XWORD.getSizeInBytes() * 8); + right = arithmeticLIRGen.emitSignExtend(right, cmpKind.getSizeInBits(), XWORD.getSizeInBits()); } append(SPARCOP3Op.newBinaryVoid(Subcc, left, right)); return mirrored; @@ -365,10 +382,10 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { - AllocatableValue scratchValue = newVariable(key.getValueKind()); + Variable scratchValue = newVariable(key.getValueKind()); AllocatableValue base = AllocatableValue.ILLEGAL; for (Constant c : strategy.getKeyConstants()) { - if (!(c instanceof JavaConstant) || !getMoveFactory().canInlineConstant((JavaConstant) c)) { + if (!getMoveFactory().canInlineConstant(c)) { base = constantTableBaseProvider.getConstantTableBase(); break; } @@ -376,7 +393,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { append(createStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue)); } - protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) { + protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, Variable scratchValue) { return new StrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue); } @@ -396,7 +413,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public Variable emitByteSwap(Value input) { Variable result = newVariable(LIRKind.combine(input)); - append(new SPARCByteSwapOp(this, result, input)); + append(new SPARCByteSwapOp(this, result, asAllocatable(input))); return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java index c075a51e3df..d24c4215f48 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java @@ -65,4 +65,14 @@ public class SPARCLIRKindTool implements LIRKindTool { public LIRKind getWordKind() { return LIRKind.value(SPARCKind.XWORD); } + + @Override + public LIRKind getNarrowOopKind() { + return LIRKind.reference(SPARCKind.WORD); + } + + @Override + public LIRKind getNarrowPointerKind() { + return LIRKind.value(SPARCKind.WORD); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java index 17395808f8e..f483eb47b76 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java @@ -91,21 +91,25 @@ public class SPARCMoveFactory implements MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - return SPARCAssembler.isSimm13(c.asInt()); - case Long: - return SPARCAssembler.isSimm13(c.asLong()); - case Object: - return c.isNull(); - default: - return false; + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + return SPARCAssembler.isSimm13(c.asInt()); + case Long: + return SPARCAssembler.isSimm13(c.asLong()); + case Object: + return c.isNull(); + default: + return false; + } } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java index a8bbdbe7f97..53c137fe193 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java @@ -29,17 +29,27 @@ import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.lir.sparc.SPARCAddressValue; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.Access; +import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; /** @@ -58,6 +68,10 @@ public class SPARCNodeMatchRules extends NodeMatchRules { return null; } + protected LIRKind getLirKind(LIRLowerableAccess access) { + return gen.getLIRKind(access.getAccessStamp()); + } + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= 64; SPARCKind toKind = null; @@ -127,6 +141,41 @@ public class SPARCNodeMatchRules extends NodeMatchRules { return emitZeroExtendMemory(access, root.getInputBits(), root.getResultBits()); } + @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") + public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { + JavaConstant constant = value.asJavaConstant(); + assert compare.condition() == Condition.EQ; + if (constant != null && cas.usages().count() == 1) { + long constantValue = constant.asLong(); + boolean successIsTrue; + if (constantValue == 0) { + successIsTrue = false; + } else if (constantValue == 1) { + successIsTrue = true; + } else { + return null; + } + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + SPARCAddressValue address = (SPARCAddressValue) operand(cas.getAddress()); + Condition condition = successIsTrue ? Condition.EQ : Condition.NE; + + Value result = getLIRGeneratorTool().emitValueCompareAndSwap(address, expectedValue, newValue); + getLIRGeneratorTool().emitCompareBranch(kind.getPlatformKind(), result, expectedValue, condition, false, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + @Override public SPARCLIRGenerator getLIRGeneratorTool() { return (SPARCLIRGenerator) super.getLIRGeneratorTool(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java similarity index 84% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java index 62e71409d9a..2770e9cba7b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java @@ -24,8 +24,9 @@ package org.graalvm.compiler.core.sparc; import java.util.ListIterator; -import org.graalvm.compiler.java.DefaultSuitesProvider; +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.PhaseSuite; import org.graalvm.compiler.phases.common.ExpandLogicPhase; @@ -33,14 +34,15 @@ import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.Suites; -public class SPARCSuitesProvider extends DefaultSuitesProvider { - public SPARCSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { +public class SPARCSuitesCreator extends DefaultSuitesCreator { + + public SPARCSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } @Override - public Suites createSuites() { - Suites s = super.createSuites(); + public Suites createSuites(OptionValues options) { + Suites s = super.createSuites(options); ListIterator> l = s.getLowTier().findPhase(ExpandLogicPhase.class); while (PhaseSuite.findNextPhase(l, ExpandLogicPhase.class)) { // Search for last occurrence of ExpandLogicPhase diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java index 03ca1c4136b..4b783878cf8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java @@ -22,10 +22,6 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; import org.graalvm.compiler.nodes.ReturnNode; @@ -37,6 +33,9 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -162,7 +161,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { sum0 = a; } else { int sum = a; - for (int i = 0; i < n; i++) { + for (int i = 1; i < n; i++) { sum += i; } sum0 = sum; @@ -313,7 +312,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); } private void compareGraphs(final String snippet, final String referenceSnippet) { @@ -331,7 +330,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { } new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); - new PartialEscapePhase(false, canonicalizer).apply(graph, context); + new PartialEscapePhase(false, canonicalizer, graph.getOptions()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ByteBufferTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ByteBufferTest.java new file mode 100644 index 00000000000..f5b0041ff9c --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ByteBufferTest.java @@ -0,0 +1,174 @@ +/* + * 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.core.test; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Collection; +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 ByteBufferTest extends GraalCompilerTest { + + class Ret { + + byte byteValue = 0; + short shortValue = 0; + int intValue = 0; + float floatValue = 0.0f; + double doubleValue = 0.0d; + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Ret)) { + return false; + } + + Ret other = (Ret) obj; + if (this.byteValue != other.byteValue) { + return false; + } + if (this.shortValue != other.shortValue) { + return false; + } + if (this.intValue != other.intValue) { + return false; + } + if (Float.floatToRawIntBits(this.floatValue) != Float.floatToRawIntBits(other.floatValue)) { + return false; + } + if (Double.doubleToRawLongBits(this.doubleValue) != Double.doubleToRawLongBits(other.doubleValue)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return String.format("0x%02x, 0x%04x, 0x%08x, 0x%04x, 0x%08x", byteValue, shortValue, intValue, Float.floatToRawIntBits(floatValue), Double.doubleToRawLongBits(doubleValue)); + } + } + + @Parameters(name = "{0}") + public static Collection data() { + ArrayList ret = new ArrayList<>(); + ret.add(new Object[]{ByteOrder.BIG_ENDIAN}); + ret.add(new Object[]{ByteOrder.LITTLE_ENDIAN}); + return ret; + } + + @Parameter public ByteOrder byteOrder; + + Ret alignedReadSnippet(byte[] arg) { + ByteBuffer buffer = ByteBuffer.wrap(arg).order(byteOrder); + + Ret ret = new Ret(); + ret.byteValue = buffer.get(); + ret.byteValue += buffer.get(); + ret.shortValue = buffer.getShort(); + ret.intValue = buffer.getInt(); + ret.doubleValue = buffer.getDouble(); + ret.floatValue = buffer.getFloat(); + + return ret; + } + + @Test + public void testReadAligned() { + byte[] input = new byte[20]; + for (int i = 0; i < 20; i++) { + input[i] = (byte) (7 * (i + 42)); + } + test("alignedReadSnippet", input); + } + + byte[] alignedWriteSnippet(byte a, byte b, short c, int d, double e, float f) { + byte[] ret = new byte[20]; + ByteBuffer buffer = ByteBuffer.wrap(ret).order(byteOrder); + + buffer.put(a); + buffer.put(b); + buffer.putShort(c); + buffer.putInt(d); + buffer.putDouble(e); + buffer.putFloat(f); + + return ret; + } + + @Test + public void testWriteAligned() { + test("alignedWriteSnippet", (byte) 5, (byte) -3, (short) 17, 42, 84.72, 1.23f); + } + + Ret unalignedReadSnippet(byte[] arg) { + ByteBuffer buffer = ByteBuffer.wrap(arg).order(byteOrder); + + Ret ret = new Ret(); + ret.byteValue = buffer.get(); + ret.shortValue = buffer.getShort(); + ret.intValue = buffer.getInt(); + ret.doubleValue = buffer.getDouble(); + ret.floatValue = buffer.getFloat(); + + return ret; + } + + @Test + public void testReadUnaligned() { + byte[] input = new byte[19]; + for (int i = 0; i < 19; i++) { + input[i] = (byte) (7 * (i + 42)); + } + test("unalignedReadSnippet", input); + } + + byte[] unalignedWriteSnippet(byte a, short b, int c, double d, float e) { + byte[] ret = new byte[20]; + ByteBuffer buffer = ByteBuffer.wrap(ret).order(byteOrder); + + buffer.put(a); + buffer.putShort(b); + buffer.putInt(c); + buffer.putDouble(d); + buffer.putFloat(e); + + return ret; + } + + @Test + public void testWriteUnaligned() { + test("unalignedWriteSnippet", (byte) -3, (short) 17, 42, 84.72, 1.23f); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java index 405652ed1e3..d183f8694e2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -41,22 +41,22 @@ import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; - +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; +import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.bytecode.BridgeMethodUtils; import org.graalvm.compiler.core.CompilerThreadFactory; import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.DelegatingDebugConfig; import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -67,20 +67,26 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase; import org.graalvm.compiler.phases.VerifyPhase.VerificationError; +import org.graalvm.compiler.phases.contract.VerifyNodeCosts; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyBailoutUsage; import org.graalvm.compiler.phases.verify.VerifyCallerSensitiveMethods; import org.graalvm.compiler.phases.verify.VerifyDebugUsage; +import org.graalvm.compiler.phases.verify.VerifyInstanceOfUsage; import org.graalvm.compiler.phases.verify.VerifyUpdateUsages; import org.graalvm.compiler.phases.verify.VerifyUsageWithEquals; import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage; import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.compiler.test.GraalTest; +import org.graalvm.word.LocationIdentity; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.Register; @@ -98,7 +104,7 @@ import jdk.vm.ci.meta.Value; * global invariants such as using {@link Object#equals(Object)} to compare certain types instead of * identity comparisons. */ -public class CheckGraalInvariants extends GraalTest { +public class CheckGraalInvariants extends GraalCompilerTest { private static boolean shouldVerifyEquals(ResolvedJavaMethod m) { if (m.getName().equals("identityEquals")) { @@ -111,17 +117,52 @@ public class CheckGraalInvariants extends GraalTest { return true; } - private static boolean shouldProcess(String classpathEntry) { - if (classpathEntry.endsWith(".jar")) { - String name = new File(classpathEntry).getName(); - return name.contains("jvmci") || name.contains("graal"); + public static String relativeFileName(String absolutePath) { + int lastFileSeparatorIndex = absolutePath.lastIndexOf(File.separator); + return absolutePath.substring(lastFileSeparatorIndex >= 0 ? lastFileSeparatorIndex : 0); + } + + public static class InvariantsTool { + + protected boolean shouldProcess(String classpathEntry) { + if (classpathEntry.endsWith(".jar")) { + String name = new File(classpathEntry).getName(); + return name.contains("jvmci") || name.contains("graal") || name.contains("jdk.internal.vm.compiler"); + } + return false; + } + + protected String getClassPath() { + String bootclasspath; + if (Java8OrEarlier) { + bootclasspath = System.getProperty("sun.boot.class.path"); + } else { + bootclasspath = System.getProperty("jdk.module.path") + File.pathSeparatorChar + System.getProperty("jdk.module.upgrade.path"); + } + return bootclasspath; + } + + protected boolean shouldLoadClass(String className) { + return !className.equals("module-info"); + } + + protected void handleClassLoadingException(Throwable t) { + GraalError.shouldNotReachHere(t); + } + + protected void handleParsingException(Throwable t) { + GraalError.shouldNotReachHere(t); } - return false; } @Test @SuppressWarnings("try") public void test() { + runTest(new InvariantsTool()); + } + + @SuppressWarnings("try") + public static void runTest(InvariantsTool tool) { RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class); Providers providers = rt.getHostBackend().getProviders(); MetaAccessProvider metaAccess = providers.getMetaAccess(); @@ -134,13 +175,12 @@ public class CheckGraalInvariants extends GraalTest { Assume.assumeTrue(VerifyPhase.class.desiredAssertionStatus()); - String propertyName = Java8OrEarlier ? "sun.boot.class.path" : "jdk.module.path"; - String bootclasspath = System.getProperty(propertyName); - Assert.assertNotNull("Cannot find value of " + propertyName, bootclasspath); + String bootclasspath = tool.getClassPath(); + Assert.assertNotNull("Cannot find boot class path", bootclasspath); final List classNames = new ArrayList<>(); for (String path : bootclasspath.split(File.pathSeparator)) { - if (shouldProcess(path)) { + if (tool.shouldProcess(path)) { try { final ZipFile zipFile = new ZipFile(new File(path)); for (final Enumeration entry = zipFile.entries(); entry.hasMoreElements();) { @@ -162,66 +202,89 @@ public class CheckGraalInvariants extends GraalTest { String property = System.getProperty(CheckGraalInvariants.class.getName() + ".filters"); String[] filters = property == null ? null : property.split(","); + OptionValues options = getInitialOptions(); CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread", new DebugConfigAccess() { @Override public GraalDebugConfig getDebugConfig() { - return DebugEnvironment.initialize(System.out); + return DebugEnvironment.ensureInitialized(options); } }); int availableProcessors = Runtime.getRuntime().availableProcessors(); ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); List errors = Collections.synchronizedList(new ArrayList<>()); - // Order outer classes before the inner classes - classNames.sort((String a, String b) -> a.compareTo(b)); - // Initialize classes in single thread to avoid deadlocking issues during initialization - List> classes = initializeClasses(classNames); - for (Class c : classes) { - String className = c.getName(); - executor.execute(() -> { - try { - checkClass(c, metaAccess); - } catch (Throwable e) { - errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); - } - }); - for (Method m : c.getDeclaredMethods()) { - if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { - // ignore - } else { - String methodName = className + "." + m.getName(); - if (matches(filters, methodName)) { - executor.execute(() -> { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { - graphBuilderSuite.apply(graph, context); - // update phi stamps - graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); - checkGraph(context, graph); - } catch (VerificationError e) { - errors.add(e.getMessage()); - } catch (LinkageError e) { - // suppress linkages errors resulting from eager resolution - } catch (BailoutException e) { - // Graal bail outs on certain patterns in Java bytecode (e.g., - // unbalanced monitors introduced by jacoco). - } catch (Throwable e) { - errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); - } - }); + for (Method m : BadUsageWithEquals.class.getDeclaredMethods()) { + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + StructuredGraph graph = new StructuredGraph.Builder(options, AllowAssumptions.YES).method(method).build(); + try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + errors.add(String.format("Expected error while checking %s", m)); + } catch (VerificationError e) { + // expected! + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", m, printStackTraceToString(e))); + } + } + if (errors.isEmpty()) { + // Order outer classes before the inner classes + classNames.sort((String a, String b) -> a.compareTo(b)); + // Initialize classes in single thread to avoid deadlocking issues during initialization + List> classes = initializeClasses(tool, classNames); + for (Class c : classes) { + String className = c.getName(); + executor.execute(() -> { + try { + checkClass(c, metaAccess); + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); + } + }); + + for (Method m : c.getDeclaredMethods()) { + if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { + // ignore + } else { + String methodName = className + "." + m.getName(); + if (matches(filters, methodName)) { + executor.execute(() -> { + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + StructuredGraph graph = new StructuredGraph.Builder(options).method(method).build(); + try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { + checkMethod(method); + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + } catch (VerificationError e) { + errors.add(e.getMessage()); + } catch (LinkageError e) { + // suppress linkages errors resulting from eager resolution + } catch (BailoutException e) { + // Graal bail outs on certain patterns in Java bytecode (e.g., + // unbalanced monitors introduced by jacoco). + } catch (Throwable e) { + try { + tool.handleParsingException(e); + } catch (Throwable t) { + errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); + } + } + }); + } } } } + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.HOURS); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } } - executor.shutdown(); - try { - executor.awaitTermination(1, TimeUnit.HOURS); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } - if (!errors.isEmpty()) { StringBuilder msg = new StringBuilder(); String nl = String.format("%n"); @@ -235,17 +298,17 @@ public class CheckGraalInvariants extends GraalTest { } } - private static List> initializeClasses(List classNames) { + private static List> initializeClasses(InvariantsTool tool, List classNames) { List> classes = new ArrayList<>(classNames.size()); for (String className : classNames) { - if (className.equals("module-info")) { + if (!tool.shouldLoadClass(className)) { continue; } try { Class c = Class.forName(className, true, CheckGraalInvariants.class.getClassLoader()); classes.add(c); - } catch (ClassNotFoundException e) { - e.printStackTrace(); + } catch (Throwable t) { + tool.handleClassLoadingException(t); } } return classes; @@ -259,6 +322,24 @@ public class CheckGraalInvariants extends GraalTest { if (c.getAnnotation(NodeInfo.class) == null) { throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName())); } + VerifyNodeCosts.verifyNodeClass(c); + } + } + + private static void checkMethod(ResolvedJavaMethod method) { + if (method.getAnnotation(Snippet.class) == null) { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + for (int i = 0; i < parameterAnnotations.length; i++) { + for (Annotation a : parameterAnnotations[i]) { + Class annotationType = a.annotationType(); + if (annotationType == ConstantParameter.class || annotationType == VarargsParameter.class || annotationType == NonNullParameter.class) { + VerificationError verificationError = new VerificationError("Parameter %d of %s is annotated with %s but the method is not annotated with %s", i, method, + annotationType.getSimpleName(), + Snippet.class.getSimpleName()); + throw verificationError; + } + } + } } } @@ -267,6 +348,8 @@ public class CheckGraalInvariants extends GraalTest { */ private static void checkGraph(HighTierContext context, StructuredGraph graph) { if (shouldVerifyEquals(graph.method())) { + // If you add a new type to test here, be sure to add appropriate + // methods to the BadUsageWithEquals class below new VerifyUsageWithEquals(Value.class).apply(graph, context); new VerifyUsageWithEquals(Register.class).apply(graph, context); new VerifyUsageWithEquals(RegisterCategory.class).apply(graph, context); @@ -283,6 +366,7 @@ public class CheckGraalInvariants extends GraalTest { new VerifyVirtualizableUsage().apply(graph, context); new VerifyUpdateUsages().apply(graph, context); new VerifyBailoutUsage().apply(graph, context); + new VerifyInstanceOfUsage().apply(graph, context); if (graph.method().isBridge()) { BridgeMethodUtils.getBridgedMethod(graph.method()); } @@ -305,4 +389,108 @@ public class CheckGraalInvariants extends GraalTest { t.printStackTrace(new PrintWriter(sw)); return sw.toString(); } + + static class BadUsageWithEquals { + Value aValue; + Register aRegister; + RegisterCategory aRegisterCategory; + JavaType aJavaType; + JavaField aJavaField; + JavaMethod aJavaMethod; + LocationIdentity aLocationIdentity; + LIRKind aLIRKind; + ArithmeticOpTable anArithmeticOpTable; + ArithmeticOpTable.Op anArithmeticOpTableOp; + + static Value aStaticValue; + static Register aStaticRegister; + static RegisterCategory aStaticRegisterCategory; + static JavaType aStaticJavaType; + static JavaField aStaticJavaField; + static JavaMethod aStaticJavaMethod; + static LocationIdentity aStaticLocationIdentity; + static LIRKind aStaticLIRKind; + static ArithmeticOpTable aStaticArithmeticOpTable; + static ArithmeticOpTable.Op aStaticArithmeticOpTableOp; + + boolean test01(Value f) { + return aValue == f; + } + + boolean test02(Register f) { + return aRegister == f; + } + + boolean test03(RegisterCategory f) { + return aRegisterCategory == f; + } + + boolean test04(JavaType f) { + return aJavaType == f; + } + + boolean test05(JavaField f) { + return aJavaField == f; + } + + boolean test06(JavaMethod f) { + return aJavaMethod == f; + } + + boolean test07(LocationIdentity f) { + return aLocationIdentity == f; + } + + boolean test08(LIRKind f) { + return aLIRKind == f; + } + + boolean test09(ArithmeticOpTable f) { + return anArithmeticOpTable == f; + } + + boolean test10(ArithmeticOpTable.Op f) { + return anArithmeticOpTableOp == f; + } + + boolean test12(Value f) { + return aStaticValue == f; + } + + boolean test13(Register f) { + return aStaticRegister == f; + } + + boolean test14(RegisterCategory f) { + return aStaticRegisterCategory == f; + } + + boolean test15(JavaType f) { + return aStaticJavaType == f; + } + + boolean test16(JavaField f) { + return aStaticJavaField == f; + } + + boolean test17(JavaMethod f) { + return aStaticJavaMethod == f; + } + + boolean test18(LocationIdentity f) { + return aStaticLocationIdentity == f; + } + + boolean test19(LIRKind f) { + return aStaticLIRKind == f; + } + + boolean test20(ArithmeticOpTable f) { + return aStaticArithmeticOpTable == f; + } + + boolean test21(ArithmeticOpTable.Op f) { + return aStaticArithmeticOpTableOp == f; + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java index 85cf35b70ce..7b5d173b407 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java @@ -90,7 +90,7 @@ public class CommonedConstantsTest extends GraalCompilerTest { @Test public void test1() { - getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); + createSuites(getInitialOptions()).getHighTier().findPhase(AbstractInliningPhase.class).remove(); test1Snippet(new String(alphabet)); test("test1Snippet", (Object) null); @@ -114,7 +114,7 @@ public class CommonedConstantsTest extends GraalCompilerTest { @Test public void test2() { - assert getSuites().getHighTier().findPhase(AbstractInliningPhase.class).hasNext(); + assert createSuites(getInitialOptions()).getHighTier().findPhase(AbstractInliningPhase.class).hasNext(); test2Snippet(new String(alphabet)); test("test2Snippet", (Object) null); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java new file mode 100644 index 00000000000..81331104a9c --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isNotEmpty; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; + +public class CompareCanonicalizerTest2 extends GraalCompilerTest { + + @SuppressWarnings("unused") private static int sink0; + @SuppressWarnings("unused") private static int sink1; + + private StructuredGraph getCanonicalizedGraph(String name) { + StructuredGraph graph = parseEager(name, AllowAssumptions.YES); + new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); + return graph; + } + + public void testIntegerTestCanonicalization(String name) { + StructuredGraph graph = getCanonicalizedGraph(name); + Assert.assertThat(graph.getNodes().filter(IntegerLessThanNode.class), isNotEmpty()); + } + + @Test + public void test0() { + testIntegerTestCanonicalization("integerTestCanonicalization0"); + } + + @Test + public void test1() { + testIntegerTestCanonicalization("integerTestCanonicalization1"); + } + + public static void integerTestCanonicalization0(int a) { + if (1 < a + 1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void integerTestCanonicalization1(int a) { + if (a - 1 < -1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java new file mode 100644 index 00000000000..ba296576c03 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class CompareCanonicalizerTest3 extends GraalCompilerTest { + + @SuppressWarnings("unused") private static int sink0; + @SuppressWarnings("unused") private static int sink1; + + @Test + public void test00() { + assertCanonicallyEqual("integerTestCanonicalization00", "referenceSnippet00"); + } + + public static void integerTestCanonicalization00(char a) { + if (a - 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @SuppressWarnings("unused") + public static void referenceSnippet00(char a) { + sink1 = 0; + } + + @Ignore("Needs better stamp support for unsigned ranges") + @Test + public void test01() { + assertCanonicallyEqual("integerTestCanonicalization01", "referenceSnippet01"); + } + + public static void integerTestCanonicalization01(char a) { + if (Integer.compareUnsigned(a - 1, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet01(char a) { + if (a != 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Ignore("Needs better stamp support for unsigned ranges") + @Test + public void test1() { + assertCanonicallyEqual("integerTestCanonicalization1", "referenceSnippet1"); + } + + public static void integerTestCanonicalization1(char a) { + if (Integer.compareUnsigned(a - 2, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet1(char a) { + if (Integer.compareUnsigned(a, 2) >= 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test2() { + assertCanonicallyEqual("integerTestCanonicalization2", "referenceSnippet2"); + } + + public static void integerTestCanonicalization2(int a) { + if (a - 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet2(int a) { + if (a != Integer.MIN_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test3() { + assertCanonicallyEqual("integerTestCanonicalization3", "referenceSnippet3"); + } + + public static void integerTestCanonicalization3(int a) { + if (a - 2 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet3(int a) { + if (a >= Integer.MIN_VALUE + 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test4() { + assertCanonicallyEqual("integerTestCanonicalization4", "referenceSnippet4"); + } + + public static void integerTestCanonicalization4(int a) { + if (a + 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet4(int a) { + if (a == Integer.MAX_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test5() { + assertCanonicallyEqual("integerTestCanonicalization5", "referenceSnippet5"); + } + + public static void integerTestCanonicalization5(int a) { + if (a + 2 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet5(int a) { + if (a > Integer.MAX_VALUE - 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test6() { + assertCanonicallyEqual("integerTestCanonicalization6", "referenceSnippet6"); + } + + public static void integerTestCanonicalization6(int a) { + if (a < a + 1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet6(int a) { + if (a != Integer.MAX_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test7() { + assertCanonicallyEqual("integerTestCanonicalization7", "referenceSnippet7"); + } + + public static void integerTestCanonicalization7(int a) { + if (a < a + 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet7(int a) { + if (a <= Integer.MAX_VALUE - 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + protected void assertCanonicallyEqual(String snippet, String reference) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + PhaseContext context = new PhaseContext(getProviders()); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, context); + canonicalizer.apply(graph, context); + StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES); + canonicalizer.apply(referenceGraph, context); + canonicalizer.apply(referenceGraph, context); + assertEquals(referenceGraph, graph, true, true); + } + + @Override + protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + return InlineInvokePlugin.InlineInfo.createStandardInlineInfo(method); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java index 1048d725105..d58022e16bd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java @@ -28,11 +28,10 @@ import static org.junit.Assert.assertTrue; import java.util.Random; -import jdk.vm.ci.meta.JavaConstant; - +import org.graalvm.compiler.core.common.calc.Condition; import org.junit.Test; -import org.graalvm.compiler.core.common.calc.Condition; +import jdk.vm.ci.meta.JavaConstant; public class ConditionTest { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java deleted file mode 100644 index b27daf302ee..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java +++ /dev/null @@ -1,289 +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.test; - -import java.lang.reflect.Field; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.nodes.IfNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; - -import sun.misc.Unsafe; - -public class ConditionalEliminationLoadFieldConstantFoldTest extends GraalCompilerTest { - public static int intSideEffect; - - public static final B FinalField = new B(10); - - private abstract static class A { - - } - - private static class B extends A { - final int a; - - B(int a) { - this.a = a; - } - } - - private static class C extends A { - final B b; - - C(B b) { - this.b = b; - } - } - - private static class D extends A { - final C c; - - D(C c) { - this.c = c; - } - } - - private static class E extends D { - final Object o; - - E(C c, Object o) { - super(c); - this.o = o; - } - } - - public static final B CONST_B = new B(10); - public static final C CONST_C = new C(CONST_B); - public static final D CONST_D = new D(CONST_C); - - public int testReadConstInBranch(B b) { - if (b == CONST_B) { - if (b.a == 5) { - intSideEffect = b.a; - } else { - intSideEffect = 10; - } - } - return 0; - } - - public int testMultipleReadsConstInBranch(D d) { - if (d == CONST_D) { - C c = d.c; - B b = c.b; - int res = b.a + 12; - if (res == 125) { - intSideEffect = 12; - } - } - return 0; - } - - public int testLoadFinalInstanceOf(E e) { - Object o = e.o; - if (o == CONST_C) { - if (o instanceof A) { - // eliminate, implied by a.x == Const(Subclass) - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - } - - public int testLoadFinalTwiceInstanceOf(E e) { - if (e.o == CONST_C) { - if (e.o instanceof A) { - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - } - - static class C1 { - final int a; - - C1(int a) { - this.a = a; - } - } - - static class C2 { - final C1 c1; - - C2(C1 c1) { - this.c1 = c1; - } - } - - public static int foldThatIsNotAllowed(C2 c2) { - // read before, this will be used to load through when folding - C1 c1Unknown = c2.c1; - - // be naughty (will be a store field after canonicalization as it has a constant offset, so - // we would be able to eliminate the inner if after an early read elimination but we would - // fold before and ce the inner if already) - // - // note: if the offset would not be constant but a parameter we would not even be able to - // remove in inner most if as we cannot rewrite the unsafe store to a store field node as - // the store might kill ANY_LOCATION - UNSAFE.putObject(c2, C2_C1_OFFSET, C1_AFTER_READ_CONST); - - if (c2 == C2_CONST) { - if (c1Unknown == C1_CONST) { - /* - * This if can be eliminated (as we rewrite the unsafe store with a constant offset - * to a store field node) but the remaining branch must be the false branch. If we - * do not fold through both field loads we will canonicalize the unsafe store to a - * store field, see the new value and can thus eliminate the true branch - * - * if we fold through the load fields we would load from the object read before the - * store so we miss the unsafe update - */ - if (c2.c1.a == 10) { - intSideEffect = 1; - return 1; - } else { - intSideEffect = 2; - return 2; - } - } else { - intSideEffect = -2; - return -2; - } - } else { - intSideEffect = -1; - return -1; - } - } - - public int testLoadFinalTwiceNoReadEliminationInstanceOf(E e) { - if (e.o == CONST_C) { - /* - * we cannot eliminate the second read of e.o although it is a final field. the call to - * System.gc (or any other memory checkpoint killing ANY_LOCATION) will prohibit the - * elimination of the second load, thus we have two different load nodes, we know that - * that first load field is a constant but we do not know for the second one, assuming - * e.o is final, as it might have been written in between - * - * this prohibits us to remove the if (fold through all loads to final fields) and the - * instance of e.o - */ - System.gc(); - C c = (C) e.o; - if (c.b.a == 10) { - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - - } - - private static final C1 C1_CONST = new C1(0); - private static final C2 C2_CONST = new C2(C1_CONST); - private static final C1 C1_AFTER_READ_CONST = new C1(10); - - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - - private static final sun.misc.Unsafe UNSAFE = getUnsafe(); - private static final long C2_C1_OFFSET; - - static { - try { - Field f = C2.class.getDeclaredField("c1"); - C2_C1_OFFSET = UNSAFE.objectFieldOffset(f); - } catch (NoSuchFieldException | SecurityException e) { - throw new RuntimeException(e); - } - } - - @Test - public void test01() { - checkGraph("testReadConstInBranch", 1); - test("testReadConstInBranch", new B(1)); - } - - @Test - public void test02() { - checkGraph("testMultipleReadsConstInBranch", 1); - } - - @Test - public void test03() { - checkGraph("testLoadFinalInstanceOf", 1); - } - - @Test - public void test04() { - checkGraph("testLoadFinalTwiceInstanceOf", 1); - } - - @Test - public void test05() { - checkGraph("testLoadFinalTwiceNoReadEliminationInstanceOf", 2); - } - - @Test(expected = AssertionError.class) - @SuppressWarnings("try") - public void test06() { - Result actual = executeActual(getResolvedJavaMethod("foldThatIsNotAllowed"), null, C2_CONST); - UNSAFE.putObject(C2_CONST, C2_C1_OFFSET, C1_CONST); - Result expected = executeExpected(getResolvedJavaMethod("foldThatIsNotAllowed"), null, C2_CONST); - Assert.assertEquals(expected.returnValue, actual.returnValue); - } - - @SuppressWarnings("try") - private StructuredGraph checkGraph(String name, int nrOfIfsAfter) { - StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - CanonicalizerPhase c = new CanonicalizerPhase(); - c.apply(g, getDefaultHighTierContext()); - new EarlyReadEliminationPhase(c).apply(g, getDefaultHighTierContext()); - new IterativeConditionalEliminationPhase(c, false).apply(g, getDefaultHighTierContext()); - Assert.assertEquals("Nr of Ifs left does not match", nrOfIfsAfter, g.getNodes().filter(IfNode.class).count()); - c.apply(g, getDefaultHighTierContext()); - return g; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java index 5f8b980e0a9..01a0236d309 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java @@ -22,19 +22,18 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; public class ConditionalEliminationMulTest extends GraalCompilerTest { public static void snippet01(int a) { - if (a == 2) { - if (a * 3 != 6) { + if (a == 3) { + if (a * 11 != 33) { shouldBeOptimizedAway(); } } @@ -42,7 +41,7 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest { public static void snippet02(int a) { if (a == 0) { - if (a * 3 != 0) { + if (a * 11 != 0) { shouldBeOptimizedAway(); } } @@ -76,11 +75,11 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest { private StructuredGraph prepareGraph(String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); + new ConditionalEliminationPhase(false).apply(graph, context); CanonicalizerPhase c = new CanonicalizerPhase(); c.apply(graph, context); - new DominatorConditionalEliminationPhase(false).apply(graph, context); + new ConditionalEliminationPhase(false).apply(graph, context); c.apply(graph, context); return graph; } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java index 73a3b98d8fc..f79580e9be4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase { + protected static int sink3; private static final String REFERENCE_SNIPPET = "referenceSnippet"; @SuppressWarnings("all") - public static int referenceSnippet(int a) { + public static void referenceSnippet(int a) { if (a == 0) { - return 1; + sink1 = 1; } - return 0; + sink0 = 0; } @Test @@ -49,21 +48,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test1Snippet(int a) { + public static void test1Snippet(int a) { if (a == 0) { if (a == 5) { - return 100; + sink2 = 100; } if (a > 100) { if (a == 0) { - return 200; + sink3 = 200; } } if (a != 2) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -72,18 +71,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test2Snippet(int a) { + public static void test2Snippet(int a) { if (a == 0) { if (a > 100) { if (a == 0) { - return 200; + sink3 = 200; } } if (a != 2) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -92,7 +91,7 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test3Snippet(int a) { + public static void test3Snippet(int a) { if (a == 0) { if (a < 1) { if (a < 2) { @@ -101,9 +100,9 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase if (a > -2) { if (a > -3) { if (a == 1) { - return 42; + sink2 = 42; } else { - return 1; + sink1 = 1; } } } @@ -112,18 +111,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } } } - return 0; + sink0 = 0; } @SuppressWarnings("all") - public static int test4Snippet(int a, int b) { + public static void test4Snippet(int a, int b) { if (b < 1) { GraalDirectives.controlFlowAnchor(); if (b < 0) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -132,21 +131,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test5Snippet(int a, int b) { + public static void test5Snippet(int a, int b) { if ((b & 3) == 0) { GraalDirectives.controlFlowAnchor(); if ((b & 7) == 0) { GraalDirectives.controlFlowAnchor(); - return 1; + sink1 = 1; } } else { GraalDirectives.controlFlowAnchor(); if ((b & 1) == 0) { GraalDirectives.controlFlowAnchor(); - return 2; + sink2 = 2; } } - return 0; + sink0 = 0; } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java index 30f8db587bb..2a79042f360 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java @@ -22,36 +22,38 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; /** * This test checks the combined action of - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} and + * {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} and * {@link org.graalvm.compiler.phases.common.LoweringPhase}. The lowering phase needs to introduce * the null checks at the correct places for the dominator conditional elimination phase to pick * them up. */ public class ConditionalEliminationTest10 extends ConditionalEliminationTestBase { + private static boolean condition1; + private static boolean condition2; + private static class TestClass { int x; } @SuppressWarnings("all") - public static int testSnippet(int a, TestClass t) { + public static int testSnippet1(TestClass t) { int result = 0; - if (a == 0) { + if (condition1) { GraalDirectives.controlFlowAnchor(); result = t.x; } @@ -61,11 +63,38 @@ public class ConditionalEliminationTest10 extends ConditionalEliminationTestBase @Test public void test1() { - StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES); + test("testSnippet1", 1); + } + + @SuppressWarnings("all") + public static int testSnippet2(TestClass t) { + int result = 0; + if (condition1) { + GraalDirectives.controlFlowAnchor(); + result = t.x; + } else { + GraalDirectives.controlFlowAnchor(); + result = t.x; + } + + if (condition2) { + result = t.x; + GraalDirectives.controlFlowAnchor(); + } + + return result; + } + + @Test + public void test2() { + test("testSnippet2", 1); + } + + private void test(String snippet, int guardCount) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - Assert.assertEquals(2, graph.getNodes().filter(GuardNode.class).count()); - new DominatorConditionalEliminationPhase(true).apply(graph, context); - Assert.assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); + new ConditionalEliminationPhase(true).apply(graph, context); + Assert.assertEquals(guardCount, graph.getNodes().filter(GuardNode.class).count()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java index 5c2b861ef15..6978bcfb669 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java @@ -22,26 +22,19 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Ignore; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase { - public ConditionalEliminationTest11() { - // Don't disable simplification - super(false); - } - @SuppressWarnings("all") public static int referenceSnippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -54,10 +47,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test1Snippet(int a) { if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -65,10 +58,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test2Snippet(int a) { if ((a & 8) == 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -81,10 +74,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test3Snippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -98,10 +91,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test4Snippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) == 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -114,7 +107,7 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test5Snippet(int a) { if ((a & 5) == 5) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 7) != 0) { return 0; @@ -130,19 +123,19 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } public static int reference6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); return 0; } @@ -153,17 +146,17 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test7Snippet(int a) { if ((a & 15) == 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) == 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference7Snippet(int a) { if ((a & 8) == 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -175,20 +168,20 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test8Snippet(int a) { if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference8Snippet(int a) { if ((a & 60) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -201,23 +194,23 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test9Snippet(int a) { if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (a != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference9Snippet(int a) { if (a != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -239,16 +232,16 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase int v = b.byteValue(); long a = v & 0xffffffff; if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; @@ -257,12 +250,13 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int reference10Snippet(ByteHolder b) { byte v = b.byteValue(); if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @Test + @Ignore public void test10() { testConditionalElimination("test10Snippet", "reference10Snippet"); } @@ -272,16 +266,16 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase long a = v & 0xffffffff; if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @@ -289,12 +283,13 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int reference11Snippet(ByteHolder b) { byte v = b.byteValue(); if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @Test + @Ignore public void test11() { testConditionalElimination("test11Snippet", "reference11Snippet"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java new file mode 100644 index 00000000000..fb1cf057578 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java @@ -0,0 +1,84 @@ +/* + * 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 org.graalvm.compiler.core.test; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Test; + +public class ConditionalEliminationTest12 extends ConditionalEliminationTestBase { + + static class A { + + } + + static class B extends A { + + } + + static class C extends B { + + } + + static class D extends C { + + } + + @SuppressWarnings({"static-method", "unused"}) + private int referenceMethod(Object a) { + if (a instanceof A) { + if (a instanceof C) { + return 1; + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + return 0; + } + + @SuppressWarnings({"static-method", "unused"}) + private int testMethod(Object a) { + if (a instanceof A) { + if (a instanceof C) { + if (a instanceof B) { + B b = (B) a; + if (b instanceof C) { + return 1; + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + return 0; + } + + @SuppressWarnings("unused") + @Test + public void testFloatingGuards() { + // Make sure class D is loaded. + D d = new D(); + testConditionalElimination("testMethod", "referenceMethod"); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java new file mode 100644 index 00000000000..ef13fb01b89 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java @@ -0,0 +1,316 @@ +/* + * 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 org.graalvm.compiler.core.test; + +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase { + + @Override + protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + return InlineInvokePlugin.InlineInfo.createStandardInlineInfo(method); + } + + public static void referenceSnippet1(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet1(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0 || a == 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet2(int a) { + if (0 < a) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet2(int a) { + if (0 < a) { + if (a == -1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet3(int a) { + if (0 < a) { + if (a == 1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + @SuppressWarnings("unused") + public static void referenceSnippet4(int a) { + sink1 = 0; + } + + public static void testSnippet4(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0 || a == 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet5(int a) { + if (a < 0) { + if (a == -1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void referenceSnippet6(int a) { + if (a < 0) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet6(int a) { + if (a < 0) { + if (a == 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet7(int a) { + if (0 < a) { + if (a == 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet8(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0 || a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet9(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet9(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0 || a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + private static int either(int a, int b) { + return (sink0 + sink1 + sink2) == 0 ? a : b; + } + + public static void testSnippet10(int a) { + if (Integer.compareUnsigned(a, a + either(1, 2)) < 0 || a == 0xffff_ffff || a == 0xffff_fffe) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet11(int a) { + if (Integer.compareUnsigned(a, Integer.MAX_VALUE + 1) > 0) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet11(int a) { + if (Integer.compareUnsigned(a, Integer.MAX_VALUE + 1) > 0) { + if (Integer.compareUnsigned(a, 42) <= 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void referenceSnippet12(int a) { + if (Integer.compareUnsigned(a, 0xffff_ffff) >= 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet12(int a) { + if (Integer.compareUnsigned(a, 0xffff_ffff) >= 0 && a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet13(int a) { + int x = either(0, 1); + if (a <= a + x) { + if (a == Integer.MAX_VALUE) { + sink2 = -2; + } + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet14(int a) { + int x = either(0, 1); + if (a < a + x) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet14(int a) { + int x = either(0, 1); + if (a < a + x) { + if (a == Integer.MAX_VALUE) { + sink2 = -2; + } + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test1() { + testConditionalElimination("testSnippet1", "referenceSnippet1"); + } + + @Test + public void test2() { + testConditionalElimination("testSnippet2", "referenceSnippet2"); + } + + @Test + public void test3() { + testConditionalElimination("testSnippet3", "testSnippet3"); + } + + @Test + public void test4() { + testConditionalElimination("testSnippet4", "referenceSnippet4"); + } + + @Test + public void test5() { + testConditionalElimination("testSnippet5", "testSnippet5"); + } + + @Test + public void test6() { + testConditionalElimination("testSnippet6", "referenceSnippet6"); + } + + @Test + public void test7() { + testConditionalElimination("testSnippet7", "referenceSnippet2"); + } + + @Test + public void test8() { + testConditionalElimination("testSnippet8", "referenceSnippet4"); + } + + @Test + public void test9() { + testConditionalElimination("testSnippet9", "referenceSnippet9"); + } + + @Test + public void test10() { + testConditionalElimination("testSnippet10", "referenceSnippet4"); + } + + @Test + public void test11() { + testConditionalElimination("testSnippet11", "referenceSnippet11"); + } + + @Test + public void test12() { + testConditionalElimination("testSnippet12", "referenceSnippet12"); + } + + @Test + public void test13() { + testConditionalElimination("testSnippet13", "testSnippet13"); + } + + @Test + public void test14() { + testConditionalElimination("testSnippet14", "referenceSnippet14"); + } + + @Override + protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) { + super.prepareGraph(graph, canonicalizer, context, applyLowering); + graph.clearAllStateAfter(); + graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA); + Debug.dump(Debug.BASIC_LEVEL, graph, "After preparation"); + canonicalizer.apply(graph, context); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java index 0e9604496b8..d1b7a123b69 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java @@ -22,22 +22,20 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase { @@ -103,7 +101,7 @@ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new FloatingReadPhase().apply(graph); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + new ConditionalEliminationPhase(true).apply(graph, context); canonicalizer.apply(graph, context); assertDeepEquals(1, graph.getNodes().filter(GuardNode.class).count()); @@ -125,7 +123,7 @@ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + new ConditionalEliminationPhase(true).apply(graph, context); canonicalizer.apply(graph, context); assertDeepEquals(0, graph.getNodes().filter(GuardNode.class).count()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java index ef8d7c7e650..31273f5ce63 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java @@ -22,13 +22,14 @@ */ package org.graalvm.compiler.core.test; +import org.junit.Ignore; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ +@Ignore public class ConditionalEliminationTest3 extends ConditionalEliminationTestBase { private static final String REFERENCE_SNIPPET = "referenceSnippet"; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java index 1daf7a5b552..db409dd3d43 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.core.test; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest4 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java index 255e5a87ec7..a32acfbbf21 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Ignore; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase { @@ -39,26 +38,30 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase interface B extends A { } + interface C extends B { + + } + static final class DistinctA { } static final class DistinctB { } - public static int reference1Snippet(Object a) { + public static void reference1Snippet(Object a) { if (a instanceof B) { - return 1; + sink1 = 1; } - return 2; + sink2 = 2; } - public static int test1Snippet(Object a) { + public static void test1Snippet(Object a) { if (a instanceof B) { if (a instanceof A) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test @@ -66,21 +69,21 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase testConditionalElimination("test1Snippet", "reference1Snippet"); } - public static int reference2Snippet(A a) { + public static void reference2Snippet(A a) { if (a instanceof B) { - return 1; + sink1 = 1; } - return 2; + sink2 = 2; } - public static int test2Snippet(A a) { + public static void test2Snippet(A a) { if (a instanceof B) { B newVal = (B) a; if (newVal != null) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test @@ -89,65 +92,104 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase } @SuppressWarnings("unused") - public static int reference3Snippet(Object a, Object b) { + public static void reference3Snippet(Object a, Object b) { if (a instanceof DistinctA) { DistinctA proxyA = (DistinctA) a; if (b instanceof DistinctB) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @SuppressWarnings("all") - public static int test3Snippet(Object a, Object b) { + public static void test3Snippet(Object a, Object b) { if (a instanceof DistinctA) { DistinctA proxyA = (DistinctA) a; if (b instanceof DistinctB) { if (proxyA == b) { - return 42; + sink0 = 42; } - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test public void test3() { - testConditionalElimination("test3Snippet", "reference3Snippet", true); + testConditionalElimination("test3Snippet", "reference3Snippet", true, false); } - public static int reference4Snippet(Object a) { + public static void reference4Snippet(Object a) { if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } - public static int test4Snippet1(Object a) { + public static void test4Snippet1(Object a) { if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof A)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } - public static int test4Snippet2(Object a) { + public static void test4Snippet2(Object a) { if (!(a instanceof A)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; + } + + @SuppressWarnings({"cast", "unused"}) + public static void test4Snippet3(Object a) { + Object pi = (A) a; + if (!(a instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + sink1 = 1; + } + + public static void test4Snippet4(Object a) { + if (!(a instanceof A)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (!(((A) a) instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + sink1 = 1; + } + + @SuppressWarnings({"cast"}) + public static void test4Snippet5(Object a) { + Object pi = (A) a; + if (pi == null) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (!(a instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + sink1 = 1; } @Test public void test4() { testConditionalElimination("test4Snippet1", "reference4Snippet"); testConditionalElimination("test4Snippet2", "reference4Snippet"); + testConditionalElimination("test4Snippet3", "reference4Snippet"); + testConditionalElimination("test4Snippet5", "reference4Snippet"); + } + + @Ignore + @Test + public void test5() { + testConditionalElimination("test4Snippet4", "reference4Snippet", false, true); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java index 761736079e3..f4e770dad12 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.core.test; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest6 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java index a6f69e3cdff..6ce50851790 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java @@ -22,13 +22,14 @@ */ package org.graalvm.compiler.core.test; +import org.junit.Ignore; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ +@Ignore public class ConditionalEliminationTest7 extends ConditionalEliminationTestBase { @SuppressWarnings("all") diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java index 52498110e4e..1a86b66c1e0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.core.test; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest8 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java index 2ac03bffd73..558ac83028c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java @@ -27,9 +27,8 @@ import org.junit.Test; import org.graalvm.compiler.api.directives.GraalDirectives; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest9 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java index 32c8f5f4644..db081e82205 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; - import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -31,50 +29,35 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTestBase extends GraalCompilerTest { - - private final boolean disableSimplification; - - protected ConditionalEliminationTestBase() { - disableSimplification = true; - } - - protected ConditionalEliminationTestBase(boolean disableSimplification) { - this.disableSimplification = disableSimplification; - } + protected static int sink0; + protected static int sink1; + protected static int sink2; protected void testConditionalElimination(String snippet, String referenceSnippet) { - testConditionalElimination(snippet, referenceSnippet, false); + testConditionalElimination(snippet, referenceSnippet, false, false); } @SuppressWarnings("try") - protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference) { + protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase(); - if (disableSimplification) { - /** - * Some tests break if simplification is done so only do it when needed. - */ - canonicalizer1.disableSimplification(); - } CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) { - canonicalizer1.apply(graph, context); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); - // new DominatorConditionalEliminationPhase(true).apply(graph, context); + prepareGraph(graph, canonicalizer1, context, applyLowering); new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); canonicalizer.apply(graph, context); canonicalizer.apply(graph, context); @@ -84,21 +67,29 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { } StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest.ReferenceGraph", referenceGraph)) { - - new ConvertDeoptimizeToGuardPhase().apply(referenceGraph, context); + prepareGraph(referenceGraph, canonicalizer, context, applyLowering); if (applyConditionalEliminationOnReference) { - new DominatorConditionalEliminationPhase(true).apply(referenceGraph, context); - canonicalizer.apply(referenceGraph, context); - canonicalizer.apply(referenceGraph, context); - } else { - canonicalizer.apply(referenceGraph, context); + new ConditionalEliminationPhase(true).apply(referenceGraph, context); } + canonicalizer.apply(referenceGraph, context); + canonicalizer.apply(referenceGraph, context); + new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { Debug.handle(t); } assertEquals(referenceGraph, graph); } + protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) { + if (applyLowering) { + new ConvertDeoptimizeToGuardPhase().apply(graph, context); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + canonicalizer.apply(graph, context); + } + canonicalizer.apply(graph, context); + new ConvertDeoptimizeToGuardPhase().apply(graph, context); + } + public void testProxies(String snippet, int expectedProxiesCreated) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); @@ -110,9 +101,9 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { canonicalizer.apply(graph, context); int baseProxyCount = graph.getNodes().filter(ProxyNode.class).count(); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + new ConditionalEliminationPhase(true).apply(graph, context); canonicalizer.apply(graph, context); - new SchedulePhase().apply(graph, context); + new SchedulePhase(graph.getOptions()).apply(graph, context); int actualProxiesCreated = graph.getNodes().filter(ProxyNode.class).count() - baseProxyCount; Assert.assertEquals(expectedProxiesCreated, actualProxiesCreated); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java index c5e2ecbb57c..5a8f6418b37 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java @@ -22,16 +22,16 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; +import static org.graalvm.compiler.core.common.util.CompilationAlarm.Options.CompilationExpirationPeriod; -import org.graalvm.compiler.common.RetryableBailoutException; +import org.graalvm.compiler.core.common.RetryableBailoutException; import org.graalvm.compiler.core.common.util.CompilationAlarm; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; +import org.junit.Test; public class CooperativePhaseTest extends GraalCompilerTest { @@ -43,9 +43,10 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); while (true) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { return; } } @@ -57,9 +58,10 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); while (true) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { throw new RetryableBailoutException("Expiring..."); } } @@ -67,13 +69,14 @@ public class CooperativePhaseTest extends GraalCompilerTest { } - private static class ParlyCooperativePhase extends Phase { + private static class PartiallyCooperativePhase extends Phase { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); for (int i = 0; i < 10; i++) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { throw new RuntimeException("Phase must not exit in the timeout path"); } } @@ -84,7 +87,8 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { - if (CompilationAlarm.hasExpired()) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); + if (compilationAlarm.hasExpired()) { throw new RuntimeException("Phase must not exit in the timeout path"); } } @@ -101,9 +105,11 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(timeout = 60_000) @SuppressWarnings("try") public void test01() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { + initializeForTimeout(); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); new CooperativePhase().apply(g); } } @@ -111,9 +117,11 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(expected = RetryableBailoutException.class, timeout = 60_000) @SuppressWarnings("try") public void test02() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { + initializeForTimeout(); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); new UnCooperativePhase().apply(g); } } @@ -121,17 +129,20 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(timeout = 60_000) @SuppressWarnings("try") public void test03() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); + initializeForTimeout(); // 0 disables alarm utility - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 0); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { - new ParlyCooperativePhase().apply(g); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 0); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); + new PartiallyCooperativePhase().apply(g); } } @Test(timeout = 60_000) @SuppressWarnings("try") public void test04() { + initializeForTimeout(); StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); new CooperativePhaseWithoutAlarm().apply(g); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java index 7655e3a3fd0..8c1e5733a9d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java @@ -35,9 +35,9 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -242,10 +242,8 @@ public class CountedLoopTest extends GraalCompilerTest { } @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - Registration r = new Registration(plugins.getInvocationPlugins(), CountedLoopTest.class); - + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { + Registration r = new Registration(invocationPlugins, CountedLoopTest.class); r.register2("get", IVProperty.class, int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { @@ -261,8 +259,7 @@ public class CountedLoopTest extends GraalCompilerTest { } } }); - - return plugins; + super.registerInvocationPlugins(invocationPlugins); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java new file mode 100644 index 00000000000..b61d3da8ffe --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java @@ -0,0 +1,70 @@ +/* + * 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.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.calc.AndNode; +import org.graalvm.compiler.nodes.calc.NotNode; +import org.graalvm.compiler.nodes.calc.OrNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.junit.Assert; +import org.junit.Test; + +public class DeMorganCanonicalizationTest extends GraalCompilerTest { + + public static int or(int a, int b) { + return ~a | ~b; + } + + public static int and(int a, int b) { + return ~a & ~b; + } + + @Test + public void testAnd() { + StructuredGraph g = parseEager("and", AllowAssumptions.NO, getInitialOptions()); + new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + Assert.assertEquals(1, g.getNodes().filter(OrNode.class).count()); + Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); + + testAgainstExpected(g.method(), new Result(and(-1, 17), null), (Object) null, -1, 17); + testAgainstExpected(g.method(), new Result(and(-1, 1), null), (Object) null, -1, 1); + testAgainstExpected(g.method(), new Result(and(-1, -1), null), (Object) null, -1, -1); + testAgainstExpected(g.method(), new Result(and(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Test + public void testOr() { + StructuredGraph g = parseEager("or", AllowAssumptions.NO, getInitialOptions()); + new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + Assert.assertEquals(1, g.getNodes().filter(AndNode.class).count()); + Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); + + testAgainstExpected(g.method(), new Result(or(-1, 17), null), (Object) null, -1, 17); + testAgainstExpected(g.method(), new Result(or(-1, 1), null), (Object) null, -1, 1); + testAgainstExpected(g.method(), new Result(or(-1, -1), null), (Object) null, -1, -1); + testAgainstExpected(g.method(), new Result(or(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java index 3ea30c0f6fa..21d00e515a0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java @@ -86,9 +86,9 @@ public class DegeneratedLoopsTest extends GraalCompilerTest { HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new CanonicalizerPhase().apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, referenceGraph, "ReferenceGraph"); + Debug.dump(Debug.BASIC_LEVEL, referenceGraph, "ReferenceGraph"); assertEquals(referenceGraph, graph); } catch (Throwable e) { throw Debug.handle(e); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java index 776497efd65..cc213a828e9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java @@ -30,8 +30,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -40,10 +39,8 @@ public final class DontReuseArgumentSpaceTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected Suites createSuites() { - try (OverrideScope scope = OptionValue.override(HighTier.Options.Inline, false)) { - return super.createSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(new OptionValues(options, HighTier.Options.Inline, false)); } @BytecodeParserNeverInline diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java index 80df81dca8d..fb06a104201 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.tiers.Suites; @@ -137,8 +138,8 @@ public class EnumSwitchTest extends GraalCompilerTest { } @Override - protected Suites createSuites() { - Suites ret = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites ret = super.createSuites(options); ret.getHighTier().prependPhase(new Phase() { @Override protected void run(StructuredGraph graph) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java index bd5c99f6897..c11a0c5483a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -74,7 +71,7 @@ public class FinalizableSubclassTest extends GraalCompilerTest { Constructor[] constructors = cl.getConstructors(); Assert.assertTrue(constructors.length == 1); final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]); - StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions, NO_PROFILING_INFO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), allowAssumptions).method(javaMethod).build(); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins()); new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf, diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java index 97851bf052a..211f18283a7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java @@ -142,7 +142,7 @@ public class FindUniqueDefaultMethodTest extends GraalCompilerTest { try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { throw Debug.handle(e); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java index e75aac37bad..0aa54277e4b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java @@ -82,7 +82,7 @@ public class FloatingReadTest extends GraphScheduleTest { } } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering"); + Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering"); Assert.assertNotNull(returnNode); Assert.assertNotNull(monitorexit); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index 9332f698b5d..5e15418654f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -31,6 +31,8 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -44,12 +46,6 @@ import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.internal.AssumptionViolatedException; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.test.Graal; @@ -62,6 +58,7 @@ import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugDumpScope; +import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; @@ -76,12 +73,14 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.BreakpointNode; +import org.graalvm.compiler.nodes.Cancellable; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -95,10 +94,11 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.compiler.options.DerivedOptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.Phase; @@ -112,12 +112,21 @@ import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.test.AddExports; import org.graalvm.compiler.test.GraalTest; +import org.graalvm.compiler.test.JLModule; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.Assumptions.Assumption; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaKind; @@ -133,7 +142,7 @@ import jdk.vm.ci.meta.SpeculationLog; *

* White box tests for Graal compiler transformations use this pattern: *

    - *
  1. Create a graph by {@linkplain #parseEager(String, AllowAssumptions) parsing} a method.
  2. + *
  3. Create a graph by {@linkplain #parseEager parsing} a method.
  4. *
  5. Manually modify the graph (e.g. replace a parameter node with a constant).
  6. *
  7. Apply a transformation to the graph.
  8. *
  9. Assert that the transformed graph is equal to an expected graph.
  10. @@ -147,12 +156,36 @@ import jdk.vm.ci.meta.SpeculationLog; *

    * These tests will be run by the {@code mx unittest} command. */ +@AddExports({"java.base/jdk.internal.org.objectweb.asm", "java.base/jdk.internal.org.objectweb.asm.tree"}) public abstract class GraalCompilerTest extends GraalTest { + /** + * Gets the initial option values provided by the Graal runtime. These are option values + * typically parsed from the command line. + */ + public static OptionValues getInitialOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + + private static final int BAILOUT_RETRY_LIMIT = 1; private final Providers providers; private final Backend backend; - private final DerivedOptionValue suites; - private final DerivedOptionValue lirSuites; + + /** + * Representative class for the {@code java.base} module. + */ + public static final Class JAVA_BASE = Class.class; + + /** + * Exports the package named {@code packageName} declared in {@code moduleMember}'s module to + * this object's module. This must be called before accessing packages that are no longer public + * as of JDK 9. + */ + protected final void exportPackage(Class moduleMember, String packageName) { + if (!Java8OrEarlier) { + JLModule.exportPackageTo(moduleMember, packageName, getClass()); + } + } /** * Denotes a test method that must be inlined by the {@link BytecodeParser}. @@ -212,8 +245,8 @@ public abstract class GraalCompilerTest extends GraalTest { protected static void shouldBeOptimizedAway() { } - protected Suites createSuites() { - Suites ret = backend.getSuites().getDefaultSuites().copy(); + protected Suites createSuites(OptionValues opts) { + Suites ret = backend.getSuites().getDefaultSuites(opts).copy(); ListIterator> iter = ret.getHighTier().findPhase(ConvertDeoptimizeToGuardPhase.class, true); if (iter == null) { /* @@ -293,16 +326,14 @@ public abstract class GraalCompilerTest extends GraalTest { return ret; } - protected LIRSuites createLIRSuites() { - LIRSuites ret = backend.getSuites().getDefaultLIRSuites().copy(); + protected LIRSuites createLIRSuites(OptionValues opts) { + LIRSuites ret = backend.getSuites().getDefaultLIRSuites(opts).copy(); return ret; } public GraalCompilerTest() { this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); this.providers = getBackend().getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } /** @@ -321,8 +352,6 @@ public abstract class GraalCompilerTest extends GraalTest { this.backend = runtime.getHostBackend(); } this.providers = backend.getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } /** @@ -333,8 +362,6 @@ public abstract class GraalCompilerTest extends GraalTest { public GraalCompilerTest(Backend backend) { this.backend = backend; this.providers = backend.getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } private Scope debugScope; @@ -347,6 +374,15 @@ public abstract class GraalCompilerTest extends GraalTest { @After public void afterTest() { + if (invocationPluginExtensions != null) { + synchronized (this) { + if (invocationPluginExtensions != null) { + extendedInvocationPlugins.removeTestPlugins(invocationPluginExtensions); + extendedInvocationPlugins = null; + invocationPluginExtensions = null; + } + } + } if (debugScope != null) { debugScope.close(); } @@ -377,13 +413,13 @@ public abstract class GraalCompilerTest extends GraalTest { String mismatchString = compareGraphStrings(expected, expectedString, graph, actualString); if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "Node count not matching - expected"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Node count not matching - actual"); + Debug.dump(Debug.BASIC_LEVEL, expected, "Node count not matching - expected"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Node count not matching - actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString); } if (!expectedString.equals(actualString)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "mismatching graphs - expected"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "mismatching graphs - actual"); + Debug.dump(Debug.BASIC_LEVEL, expected, "mismatching graphs - expected"); + Debug.dump(Debug.BASIC_LEVEL, graph, "mismatching graphs - actual"); Assert.fail(mismatchString); } } @@ -449,22 +485,25 @@ public abstract class GraalCompilerTest extends GraalTest { StringBuilder result = new StringBuilder(); for (Block block : scheduleResult.getCFG().getBlocks()) { - result.append("Block " + block + " "); + result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); for (Block succ : block.getSuccessors()) { - result.append(succ + " "); + result.append(succ).append(' '); } - result.append("\n"); + result.append('\n'); for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { if (node instanceof ValueNode && node.isAlive()) { - if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) { + if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode || node instanceof ParameterNode)) { if (node instanceof ConstantNode) { String name = checkConstants ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); - String str = name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n"); - constantsLines.add(str); + if (excludeVirtual) { + constantsLines.add(name); + } else { + constantsLines.add(name + " (" + filteredUsageCount(node) + ")"); + } } else { int id; if (canonicalId.get(node) != null) { @@ -474,8 +513,17 @@ public abstract class GraalCompilerTest extends GraalTest { canonicalId.set(node, id); } String name = node.getClass().getSimpleName(); - String str = " " + id + "|" + name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n"); - result.append(str); + result.append(" ").append(id).append('|').append(name); + if (node instanceof AccessFieldNode) { + result.append('#'); + result.append(((AccessFieldNode) node).field()); + } + if (!excludeVirtual) { + result.append(" ("); + result.append(filteredUsageCount(node)); + result.append(')'); + } + result.append('\n'); } } } @@ -483,14 +531,14 @@ public abstract class GraalCompilerTest extends GraalTest { } StringBuilder constantsLinesResult = new StringBuilder(); - constantsLinesResult.append(constantsLines.size() + " constants:\n"); + constantsLinesResult.append(constantsLines.size()).append(" constants:\n"); Collections.sort(constantsLines); for (String s : constantsLines) { constantsLinesResult.append(s); - constantsLinesResult.append("\n"); + constantsLinesResult.append('\n'); } - return constantsLines.toString() + result.toString(); + return constantsLinesResult.toString() + result.toString(); } /** @@ -512,15 +560,15 @@ public abstract class GraalCompilerTest extends GraalTest { StringBuilder result = new StringBuilder(); Block[] blocks = scheduleResult.getCFG().getBlocks(); for (Block block : blocks) { - result.append("Block " + block + " "); + result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); for (Block succ : block.getSuccessors()) { - result.append(succ + " "); + result.append(succ).append(' '); } - result.append("\n"); + result.append('\n'); for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { result.append(String.format("%1S\n", node)); } @@ -532,14 +580,6 @@ public abstract class GraalCompilerTest extends GraalTest { return backend; } - protected Suites getSuites() { - return suites.getValue(); - } - - protected LIRSuites getLIRSuites() { - return lirSuites.getValue(); - } - protected final Providers getProviders() { return providers; } @@ -617,11 +657,12 @@ public abstract class GraalCompilerTest extends GraalTest { } } - protected Object referenceInvoke(ResolvedJavaMethod method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + protected Object referenceInvoke(ResolvedJavaMethod method, Object receiver, Object... args) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { return invoke(method, receiver, args); } - protected static class Result { + public static class Result { public final Object returnValue; public final Throwable exception; @@ -665,12 +706,16 @@ public abstract class GraalCompilerTest extends GraalTest { } protected Result executeActual(ResolvedJavaMethod method, Object receiver, Object... args) { + return executeActual(getInitialOptions(), method, receiver, args); + } + + protected Result executeActual(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { before(method); Object[] executeArgs = argsWithReceiver(receiver, args); checkArgs(method, executeArgs); - InstalledCode compiledMethod = getCode(method); + InstalledCode compiledMethod = getCode(method, options); try { return new Result(compiledMethod.executeVarargs(executeArgs), null); } catch (Throwable e) { @@ -718,14 +763,19 @@ public abstract class GraalCompilerTest extends GraalTest { return applyArgSuppliers(executeArgs); } - protected void test(String name, Object... args) { + protected final Result test(String name, Object... args) { + return test(getInitialOptions(), name, args); + } + + protected final Result test(OptionValues options, String name, Object... args) { try { ResolvedJavaMethod method = getResolvedJavaMethod(name); Object receiver = method.isStatic() ? null : this; - test(method, receiver, args); + return test(options, method, receiver, args); } catch (AssumptionViolatedException e) { // Suppress so that subsequent calls to this method within the // same Junit @Test annotated method can proceed. + return null; } } @@ -745,12 +795,16 @@ public abstract class GraalCompilerTest extends GraalTest { return supplier; } - protected void test(ResolvedJavaMethod method, Object receiver, Object... args) { + protected Result test(ResolvedJavaMethod method, Object receiver, Object... args) { + return test(getInitialOptions(), method, receiver, args); + } + + protected Result test(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { Result expect = executeExpected(method, receiver, args); - if (getCodeCache() == null) { - return; + if (getCodeCache() != null) { + testAgainstExpected(options, method, expect, receiver, args); } - testAgainstExpected(method, expect, receiver, args); + return expect; } /** @@ -770,17 +824,30 @@ public abstract class GraalCompilerTest extends GraalTest { return res; } - protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { - testAgainstExpected(method, expect, Collections. emptySet(), receiver, args); + protected final void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { + testAgainstExpected(getInitialOptions(), method, expect, Collections. emptySet(), receiver, args); } - protected Result executeActualCheckDeopt(ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { + protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + testAgainstExpected(getInitialOptions(), method, expect, shouldNotDeopt, receiver, args); + } + + protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { + testAgainstExpected(options, method, expect, Collections. emptySet(), receiver, args); + } + + protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + Result actual = executeActualCheckDeopt(options, method, shouldNotDeopt, receiver, args); + assertEquals(expect, actual); + } + + protected Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { Map deoptCounts = new EnumMap<>(DeoptimizationReason.class); ProfilingInfo profile = method.getProfilingInfo(); for (DeoptimizationReason reason : shouldNotDeopt) { deoptCounts.put(reason, profile.getDeoptimizationCount(reason)); } - Result actual = executeActual(method, receiver, args); + Result actual = executeActual(options, method, receiver, args); profile = method.getProfilingInfo(); // profile can change after execution for (DeoptimizationReason reason : shouldNotDeopt) { Assert.assertEquals((int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason)); @@ -801,19 +868,18 @@ public abstract class GraalCompilerTest extends GraalTest { } } - protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { - Result actual = executeActualCheckDeopt(method, shouldNotDeopt, receiver, args); - assertEquals(expect, actual); - } - private Map cache = new HashMap<>(); /** * Gets installed code for a given method, compiling it first if necessary. The graph is parsed - * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions) eagerly}. + * {@link #parseEager eagerly}. */ - protected InstalledCode getCode(ResolvedJavaMethod method) { - return getCode(method, null); + protected final InstalledCode getCode(ResolvedJavaMethod method) { + return getCode(method, null, false, false, getInitialOptions()); + } + + protected final InstalledCode getCode(ResolvedJavaMethod method, OptionValues options) { + return getCode(method, null, false, false, options); } /** @@ -823,12 +889,8 @@ public abstract class GraalCompilerTest extends GraalTest { * @param graph the graph to be compiled. If null, a graph will be obtained from * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. */ - protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { - return getCode(installedCodeOwner, graph, false); - } - - protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph0, boolean forceCompile) { - return getCode(installedCodeOwner, graph0, forceCompile, false); + protected final InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { + return getCode(installedCodeOwner, graph, false, false, graph == null ? getInitialOptions() : graph.getOptions()); } /** @@ -839,10 +901,24 @@ public abstract class GraalCompilerTest extends GraalTest { * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. * @param forceCompile specifies whether to ignore any previous code cached for the (method, * key) pair - * @param installDefault specifies whether to install as the default implementation + */ + protected final InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) { + return getCode(installedCodeOwner, graph, forceCompile, false, graph == null ? getInitialOptions() : graph.getOptions()); + } + + /** + * Gets installed code for a given method and graph, compiling it first if necessary. + * + * @param installedCodeOwner the method the compiled code will be associated with when installed + * @param graph the graph to be compiled. If null, a graph will be obtained from + * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. + * @param forceCompile specifies whether to ignore any previous code cached for the (method, + * key) pair + * @param installAsDefault specifies whether to install as the default implementation + * @param options the options that will be used in {@link #parseForCompile(ResolvedJavaMethod)} */ @SuppressWarnings("try") - protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installDefault) { + protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { if (!forceCompile) { InstalledCode cached = cache.get(installedCodeOwner); if (cached != null) { @@ -851,41 +927,54 @@ public abstract class GraalCompilerTest extends GraalTest { } } } + // loop for retrying compilation + for (int retry = 0; retry <= BAILOUT_RETRY_LIMIT; retry++) { + final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph); - final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph); - - InstalledCode installedCode = null; - try (AllocSpy spy = AllocSpy.open(installedCodeOwner); Scope ds = Debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { - final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); - if (printCompilation) { - TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s ...", id, installedCodeOwner.getDeclaringClass().getName(), installedCodeOwner.getName(), installedCodeOwner.getSignature())); - } - long start = System.currentTimeMillis(); - CompilationResult compResult = compile(installedCodeOwner, graph, id); - if (printCompilation) { - TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); - } - - try (Scope s = Debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult)) { - if (installDefault) { - installedCode = addDefaultMethod(installedCodeOwner, compResult); - } else { - installedCode = addMethod(installedCodeOwner, compResult); + InstalledCode installedCode = null; + try (AllocSpy spy = AllocSpy.open(installedCodeOwner); Scope ds = Debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { + final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); + if (printCompilation) { + TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s ...", id, installedCodeOwner.getDeclaringClass().getName(), installedCodeOwner.getName(), + installedCodeOwner.getSignature())); } - if (installedCode == null) { - throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)")); + long start = System.currentTimeMillis(); + CompilationResult compResult = compile(installedCodeOwner, graph, new CompilationResult(), id, options); + if (printCompilation) { + TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); + } + + try (Scope s = Debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult)) { + try { + if (installAsDefault) { + installedCode = addDefaultMethod(installedCodeOwner, compResult); + } else { + installedCode = addMethod(installedCodeOwner, compResult); + } + if (installedCode == null) { + throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)")); + } + } catch (BailoutException e) { + if (retry <= BAILOUT_RETRY_LIMIT && graph == null && !e.isPermanent()) { + // retry (if there is no predefined graph) + TTY.println(String.format("Restart compilation %s (%s) due to a non-permanent bailout!", installedCodeOwner, id)); + continue; + } + throw e; + } + } catch (Throwable e) { + throw Debug.handle(e); } } catch (Throwable e) { throw Debug.handle(e); } - } catch (Throwable e) { - throw Debug.handle(e); - } - if (!forceCompile) { - cache.put(installedCodeOwner, installedCode); + if (!forceCompile) { + cache.put(installedCodeOwner, installedCode); + } + return installedCode; } - return installedCode; + throw GraalError.shouldNotReachHere(); } /** @@ -893,15 +982,18 @@ public abstract class GraalCompilerTest extends GraalTest { * {@link #compile(ResolvedJavaMethod, StructuredGraph)} if the second parameter to that method * is null. * - * The default implementation in {@link GraalCompilerTest} is to call - * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions)}. + * The default implementation in {@link GraalCompilerTest} is to call {@link #parseEager}. */ - protected final StructuredGraph parseForCompile(ResolvedJavaMethod method) { - return parseEager(method, AllowAssumptions.YES); + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, OptionValues options) { + return parseEager(method, AllowAssumptions.YES, getCompilationId(method), options); } - protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId) { - return parseEager(method, AllowAssumptions.YES, compilationId); + protected final StructuredGraph parseForCompile(ResolvedJavaMethod method) { + return parseEager(method, AllowAssumptions.YES, getCompilationId(method), getInitialOptions()); + } + + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { + return parseEager(method, AllowAssumptions.YES, compilationId, options); } /** @@ -913,11 +1005,18 @@ public abstract class GraalCompilerTest extends GraalTest { * {@link #parseForCompile(ResolvedJavaMethod)}. */ protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { - return compile(installedCodeOwner, graph, getOrCreateCompilationId(installedCodeOwner, graph)); + OptionValues options = graph == null ? getInitialOptions() : graph.getOptions(); + return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options); } - protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) { - return compile(installedCodeOwner, graph, new CompilationResult(), compilationId); + protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) { + OptionValues options = graph == null ? getInitialOptions() : graph.getOptions(); + return compile(installedCodeOwner, graph, new CompilationResult(), compilationId, options); + } + + protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, OptionValues options) { + assert graph == null || graph.getOptions() == options; + return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options); } /** @@ -927,16 +1026,16 @@ public abstract class GraalCompilerTest extends GraalTest { * @param graph the graph to be compiled for {@code installedCodeOwner}. If null, a graph will * be obtained from {@code installedCodeOwner} via * {@link #parseForCompile(ResolvedJavaMethod)}. - * @param compilationResult * @param compilationId */ @SuppressWarnings("try") - protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId) { - StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, compilationId) : graph; + protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId, OptionValues options) { + StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, compilationId, options) : graph; lastCompiledGraph = graphToCompile; try (Scope s = Debug.scope("Compile", graphToCompile)) { + assert options != null; Request request = new Request<>(graphToCompile, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, - graphToCompile.getProfilingInfo(), getSuites(), getLIRSuites(), compilationResult, CompilationResultBuilderFactory.Default); + graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default); return GraalCompiler.compile(request); } catch (Throwable e) { throw Debug.handle(e); @@ -957,12 +1056,12 @@ public abstract class GraalCompilerTest extends GraalTest { return backend.createDefaultInstalledCode(method, compilationResult); } - private final Map methodMap = new HashMap<>(); + private final Map methodMap = new HashMap<>(); /** * Converts a reflection {@link Method} to a {@link ResolvedJavaMethod}. */ - protected ResolvedJavaMethod asResolvedJavaMethod(Method method) { + protected ResolvedJavaMethod asResolvedJavaMethod(Executable method) { ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); methodMap.put(javaMethod, method); return javaMethod; @@ -984,17 +1083,21 @@ public abstract class GraalCompilerTest extends GraalTest { * Gets the reflection {@link Method} from which a given {@link ResolvedJavaMethod} was created * or null if {@code javaMethod} does not correspond to a reflection method. */ - protected Method lookupMethod(ResolvedJavaMethod javaMethod) { + protected Executable lookupMethod(ResolvedJavaMethod javaMethod) { return methodMap.get(javaMethod); } - protected Object invoke(ResolvedJavaMethod javaMethod, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Method method = lookupMethod(javaMethod); + protected Object invoke(ResolvedJavaMethod javaMethod, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { + Executable method = lookupMethod(javaMethod); Assert.assertTrue(method != null); if (!method.isAccessible()) { method.setAccessible(true); } - return method.invoke(receiver, applyArgSuppliers(args)); + if (method instanceof Method) { + return ((Method) method).invoke(receiver, applyArgSuppliers(args)); + } + assert receiver == null : "no receiver for constructor invokes"; + return ((Constructor) method).newInstance(applyArgSuppliers(args)); } /** @@ -1002,21 +1105,21 @@ public abstract class GraalCompilerTest extends GraalTest { * produce a graph. * * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { + protected final StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { return parseProfiled(getResolvedJavaMethod(methodName), allowAssumptions); } /** * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault default} mode to * produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected final StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseProfiled(m, allowAssumptions, getCompilationId(m)); - } - - protected StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getDefaultGraphBuilderSuite(), allowAssumptions, compilationId); + protected final StructuredGraph parseProfiled(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parse1(method, getDefaultGraphBuilderSuite(), allowAssumptions, getCompilationId(method), getInitialOptions()); } /** @@ -1024,39 +1127,85 @@ public abstract class GraalCompilerTest extends GraalTest { * set to true to produce a graph. * * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions) { - return parseEager(getResolvedJavaMethod(methodName), allowAssumptions); + return parseEager(getResolvedJavaMethod(methodName), allowAssumptions, getInitialOptions()); } /** * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} * set to true to produce a graph. + * + * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param options the option values to be used when compiling the graph */ - protected final StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseEager(m, allowAssumptions, getCompilationId(m)); + protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions, OptionValues options) { + return parseEager(getResolvedJavaMethod(methodName), allowAssumptions, options); } - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)), allowAssumptions, compilationId); + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + */ + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parseEager(method, allowAssumptions, getCompilationId(method), getInitialOptions()); + } + + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param options the option values to be used when compiling the graph + */ + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, OptionValues options) { + return parseEager(method, allowAssumptions, getCompilationId(method), options); + } + + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param compilationId the compilation identifier to be associated with the graph + * @param options the option values to be used when compiling the graph + */ + protected StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + return parse1(method, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)), allowAssumptions, compilationId, options); } /** * Parses a Java method using {@linkplain GraphBuilderConfiguration#withFullInfopoints(boolean) * full debug} set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected final StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseDebug(m, allowAssumptions, getCompilationId(m)); - } - - protected StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)), allowAssumptions, compilationId); + protected StructuredGraph parseDebug(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parse1(method, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)), allowAssumptions, getCompilationId(method), + getInitialOptions()); } @SuppressWarnings("try") - private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { + private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, + OptionValues options) { assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod; - StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions, getSpeculationLog(), compilationId); + // @formatter:off + StructuredGraph graph = new StructuredGraph.Builder(options, allowAssumptions). + method(javaMethod). + speculationLog(getSpeculationLog()). + useProfilingInfo(true). + compilationId(compilationId). + cancellable(getCancellable(javaMethod)). + build(); + // @formatter:on try (Scope ds = Debug.scope("Parsing", javaMethod, graph)) { graphBuilderSuite.apply(graph, getDefaultHighTierContext()); return graph; @@ -1065,6 +1214,16 @@ public abstract class GraalCompilerTest extends GraalTest { } } + /** + * Gets the cancellable that should be associated with a graph being created by any of the + * {@code parse...()} methods. + * + * @param method the method being parsed into a graph + */ + protected Cancellable getCancellable(ResolvedJavaMethod method) { + return null; + } + protected Plugins getDefaultGraphBuilderPlugins() { PhaseSuite suite = backend.getSuites().getDefaultGraphBuilderSuite(); Plugins defaultPlugins = ((GraphBuilderPhase) suite.findPhase(GraphBuilderPhase.class).previous()).getGraphBuilderConfig().getPlugins(); @@ -1077,17 +1236,16 @@ public abstract class GraalCompilerTest extends GraalTest { return backend.getSuites().getDefaultGraphBuilderSuite().copy(); } - protected PhaseSuite getCustomGraphBuilderSuite(GraphBuilderConfiguration gbConf) { - PhaseSuite suite = getDefaultGraphBuilderSuite(); - ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); - GraphBuilderConfiguration gbConfCopy = editGraphBuilderConfiguration(gbConf.copy()); - iterator.remove(); - iterator.add(new GraphBuilderPhase(gbConfCopy)); - return suite; - } - - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); + /** + * Registers extra invocation plugins for this test. The extra plugins are removed in the + * {@link #afterTest()} method. + * + * Subclasses overriding this method should always call the same method on the super class in + * case it wants to register plugins. + * + * @param invocationPlugins + */ + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { invocationPlugins.register(new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { @@ -1109,7 +1267,41 @@ public abstract class GraalCompilerTest extends GraalTest { return true; } }, GraalCompilerTest.class, "shouldBeOptimizedAway"); + } + /** + * The {@link #testN(int, String, Object...)} method means multiple threads trying to initialize + * this field. + */ + private volatile InvocationPlugins invocationPluginExtensions; + + private InvocationPlugins extendedInvocationPlugins; + + protected PhaseSuite getCustomGraphBuilderSuite(GraphBuilderConfiguration gbConf) { + PhaseSuite suite = getDefaultGraphBuilderSuite(); + ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); + initializeInvocationPluginExtensions(); + GraphBuilderConfiguration gbConfCopy = editGraphBuilderConfiguration(gbConf.copy()); + iterator.remove(); + iterator.add(new GraphBuilderPhase(gbConfCopy)); + return suite; + } + + private void initializeInvocationPluginExtensions() { + if (invocationPluginExtensions == null) { + synchronized (this) { + if (invocationPluginExtensions == null) { + InvocationPlugins invocationPlugins = new InvocationPlugins(); + registerInvocationPlugins(invocationPlugins); + extendedInvocationPlugins = getReplacements().getGraphBuilderPlugins().getInvocationPlugins(); + extendedInvocationPlugins.addTestPlugins(invocationPlugins, null); + invocationPluginExtensions = invocationPlugins; + } + } + } + } + + protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { conf.getPlugins().prependInlineInvokePlugin(new InlineInvokePlugin() { @Override @@ -1186,4 +1378,13 @@ public abstract class GraalCompilerTest extends GraalTest { protected boolean isArchitecture(String name) { return name.equals(backend.getTarget().arch.getName()); } + + /** + * This method should be called in "timeout" tests which JUnit runs in a different thread. + */ + public static void initializeForTimeout() { + // timeout tests run in a separate thread which needs the DebugEnvironment to be + // initialized + DebugEnvironment.ensureInitialized(getInitialOptions()); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java index 6dd6b2b5b19..7f319c38a80 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java @@ -71,7 +71,7 @@ public class GraphEncoderTest extends GraalCompilerTest { encoder.prepare(originalGraph); } encoder.finishPrepare(); - Map startOffsets = new HashMap<>(); + Map startOffsets = new HashMap<>(); for (StructuredGraph originalGraph : originalGraphs) { startOffsets.put(originalGraph, encoder.encode(originalGraph)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java deleted file mode 100644 index ee219719139..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java +++ /dev/null @@ -1,117 +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.core.test; - -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.BeginNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.GuardNode; -import org.graalvm.compiler.nodes.LogicNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.java.InstanceOfNode; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.spi.ValueProxy; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; -import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; - -public class GuardEliminationCornerCasesTest extends GraalCompilerTest { - - static class A { - - } - - static class B extends A { - - } - - static class C extends B { - - } - - static class D extends C { - - } - - @SuppressWarnings({"static-method", "unused"}) - private int testMethod(Object a) { - if (a instanceof A) { - if (a instanceof C) { - if (a instanceof B) { - B b = (B) a; - if (b instanceof C) { - return 1; - } else { - GraalDirectives.deoptimizeAndInvalidate(); - } - } - } else { - GraalDirectives.deoptimizeAndInvalidate(); - } - } - return 0; - } - - @Test - public void testFloatingGuards() { - HighTierContext context = getDefaultHighTierContext(); - StructuredGraph graph = parseEager("testMethod", AllowAssumptions.YES); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after parsing"); - - GuardNode myGuardNode = null; - for (Node n : graph.getNodes()) { - if (n instanceof GuardNode) { - GuardNode guardNode = (GuardNode) n; - LogicNode condition = guardNode.getCondition(); - if (condition instanceof InstanceOfNode) { - InstanceOfNode instanceOfNode = (InstanceOfNode) condition; - if (instanceOfNode.getValue() instanceof ValueProxy) { - myGuardNode = guardNode; - break; - } - } - } - } - - AbstractBeginNode myBegin = (AbstractBeginNode) myGuardNode.getAnchor(); - AbstractBeginNode prevBegin = BeginNode.prevBegin((FixedNode) myBegin.predecessor()); - myGuardNode.setAnchor(prevBegin); - - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after manual modification"); - graph.reverseUsageOrder(); - new DominatorConditionalEliminationPhase(true).apply(graph, context); - new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST).apply(graph); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java index a84872e309b..5a4740f25be 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java @@ -24,10 +24,6 @@ package org.graalvm.compiler.core.test; import java.util.List; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConstantNode; @@ -39,12 +35,15 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -111,15 +110,14 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { private StructuredGraph parsedForCompile; @Override - protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId) { - graph = super.parseForCompile(method, compilationId); + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { + graph = super.parseForCompile(method, compilationId, options); parsedForCompile = (StructuredGraph) graph.copy(); return graph; } @Override - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { Registration r = new Registration(invocationPlugins, Super.class); r.register1("getAge", Receiver.class, new InvocationPlugin() { @@ -131,7 +129,7 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { return true; } }); - return super.editGraphBuilderConfiguration(conf); + super.registerInvocationPlugins(invocationPlugins); } public static int referenceMakeSuperAge() { @@ -209,7 +207,7 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { @Override public int hashCode() { int result = ((identity == null) ? 0 : identity.hashCode()); - return result + object.hashCode(); + return result + System.identityHashCode(object); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java index eb9b5ce1162..6ee99a34f14 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java @@ -22,17 +22,18 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.core.phases.MidTier; import org.graalvm.compiler.nodes.InvokeNode; +import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.junit.Assert; +import org.junit.Test; public class HashCodeTest extends GraalCompilerTest { @@ -143,7 +144,9 @@ public class HashCodeTest extends GraalCompilerTest { private void checkForGuardedIntrinsicPattern(String name) { StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - Assert.assertEquals(1, g.getNodes().filter(InvokeNode.class).count()); + int invokeNodeCount = g.getNodes().filter(InvokeNode.class).count(); + int invokeWithExceptionNodeCount = g.getNodes().filter(InvokeWithExceptionNode.class).count(); + Assert.assertEquals(1, invokeNodeCount + invokeWithExceptionNodeCount); Assert.assertEquals(1, g.getNodes().filter(LoadHubNode.class).count()); Assert.assertEquals(1, g.getNodes().filter(LoadMethodNode.class).count()); } @@ -151,8 +154,9 @@ public class HashCodeTest extends GraalCompilerTest { @SuppressWarnings("try") private StructuredGraph buildGraphAfterMidTier(String name) { StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - new HighTier().apply(g, getDefaultHighTierContext()); - new MidTier().apply(g, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, g.getProfilingInfo())); + OptionValues options = getInitialOptions(); + new HighTier(options).apply(g, getDefaultHighTierContext()); + new MidTier(options).apply(g, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, g.getProfilingInfo())); return g; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java index 0cf12a00ffb..afa51c73db7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java @@ -38,7 +38,6 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -148,7 +147,7 @@ public class IfCanonicalizerTest extends GraalCompilerTest { @Test public void test6() { - testCombinedIf("test6Snippet", 3); + testCombinedIf("test6Snippet", 4); test("test6Snippet", new int[]{0}); } @@ -197,6 +196,33 @@ public class IfCanonicalizerTest extends GraalCompilerTest { return (n < 0) ? 1 : (n >= 1024) ? 1024 : n + 1; } + @Test + public void test10() { + // Exercise NormalizeCompareNode with long values + test("test10Snippet", 0, 1); + } + + public static long test10Snippet(int x, int y) { + return (x < y) ? -1L : ((x == y) ? 0L : 1L); + } + + @Test + public void test11() { + test("test11Snippet", 0, 1); + } + + public static long test11Snippet(int x, int y) { + long normalizeCompare = normalizeCompareLong(x, y); + if (normalizeCompare == 0) { + return 5; + } + return 1; + } + + private static Long normalizeCompareLong(int x, int y) { + return (x < y) ? -1L : ((x == y) ? 0L : 1L); + } + private void testCombinedIf(String snippet, int count) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); @@ -205,7 +231,6 @@ public class IfCanonicalizerTest extends GraalCompilerTest { MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new ValueAnchorCleanupPhase().apply(graph); new CanonicalizerPhase().apply(graph, context); assertDeepEquals(count, graph.getNodes().filter(IfNode.class).count()); } @@ -219,7 +244,7 @@ public class IfCanonicalizerTest extends GraalCompilerTest { n.replaceFirstInput(param, constant); } } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) { fs.replaceFirstInput(param, null); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java index f93a6f7c3f8..93c8f0fc904 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java @@ -25,10 +25,6 @@ package org.graalvm.compiler.core.test; import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; import static org.junit.Assert.assertNotNull; -import jdk.vm.ci.code.site.Call; -import jdk.vm.ci.code.site.Infopoint; -import jdk.vm.ci.code.site.InfopointReason; -import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; @@ -42,6 +38,11 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; +import jdk.vm.ci.code.site.Call; +import jdk.vm.ci.code.site.Infopoint; +import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.meta.ResolvedJavaMethod; + /** * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons. */ @@ -63,7 +64,7 @@ public class InfopointReasonTest extends GraalCompilerTest { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); final StructuredGraph graph = parseEager(method, AllowAssumptions.YES); final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), - getSuites(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); if (sp instanceof Call) { @@ -75,7 +76,7 @@ public class InfopointReasonTest extends GraalCompilerTest { @Test public void lineInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseDebug(method, AllowAssumptions.from(OptAssumptions.getValue())); + final StructuredGraph graph = parseDebug(method, AllowAssumptions.ifTrue(OptAssumptions.getValue(getInitialOptions()))); int graphLineSPs = 0; for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { if (ipn.getReason() == InfopointReason.BYTECODE_POSITION) { @@ -84,8 +85,8 @@ public class InfopointReasonTest extends GraalCompilerTest { } assertTrue(graphLineSPs > 0); PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)); - final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), getSuites(), - getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java index 7a450de3281..cb6e4e09b58 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java @@ -22,12 +22,11 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.InvalidInstalledCodeException; - +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; public class InstalledCodeInvalidationTest extends GraalCompilerTest { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java index 601fc26ad90..4dca5901e9b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java @@ -37,7 +37,7 @@ import org.objectweb.asm.Opcodes; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; -public final class InterfaceMethodHandleTest extends GraalCompilerTest implements Opcodes { +public final class InterfaceMethodHandleTest extends GraalCompilerTest { private static final MethodHandle INTERFACE_HANDLE_M; private static final MethodHandle INTERFACE_HANDLE_M2; @@ -135,58 +135,65 @@ public final class InterfaceMethodHandleTest extends GraalCompilerTest implement private static final String BASENAME = InterfaceMethodHandleTest.class.getName(); private static final String NAME = BASENAME + "_B"; - private AsmLoader loader = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); + private final AsmLoader loader; - /** - * Construct a type which claims to implement {@link I} but with incorrect access on {@link I#m} - * so that an exception must be thrown. - */ - public static byte[] bytesForB() { + public InterfaceMethodHandleTest() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + loader = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); + } - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - String jvmName = NAME.replace('.', '/'); - cw.visit(52, ACC_SUPER | ACC_PUBLIC, jvmName, null, "java/lang/Object", new String[]{BASENAME.replace('.', '/') + "$I"}); + static class Gen implements Opcodes { + /** + * Construct a type which claims to implement {@link I} but with incorrect access on + * {@link I#m} so that an exception must be thrown. + */ + public static byte[] bytesForB() { - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + String jvmName = NAME.replace('.', '/'); + cw.visit(52, ACC_SUPER | ACC_PUBLIC, jvmName, null, "java/lang/Object", new String[]{BASENAME.replace('.', '/') + "$I"}); - mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null); - mv.visitCode(); - l0 = new Label(); - mv.visitLabel(l0); - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 1); + mv.visitEnd(); - cw.visitEnd(); + mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null); + mv.visitCode(); + l0 = new Label(); + mv.visitLabel(l0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 1); + mv.visitEnd(); - mv = cw.visitMethod(ACC_PRIVATE, "m2", "(IIIIIIIIII)I", null, null); - mv.visitCode(); - l0 = new Label(); - mv.visitLabel(l0); - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 11); - mv.visitEnd(); + cw.visitEnd(); - cw.visitEnd(); + mv = cw.visitMethod(ACC_PRIVATE, "m2", "(IIIIIIIIII)I", null, null); + mv.visitCode(); + l0 = new Label(); + mv.visitLabel(l0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 11); + mv.visitEnd(); - return cw.toByteArray(); + cw.visitEnd(); + + return cw.toByteArray(); + } } public static class AsmLoader extends ExportingClassLoader { @@ -202,7 +209,7 @@ public final class InterfaceMethodHandleTest extends GraalCompilerTest implement if (loaded != null) { return loaded; } - byte[] bytes = bytesForB(); + byte[] bytes = Gen.bytesForB(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java index 9e0d5a9430b..ac909fc5d1f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java @@ -25,7 +25,8 @@ package org.graalvm.compiler.core.test; import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; - +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.MonitorExitNode; @@ -35,7 +36,6 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.LockEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -92,6 +92,26 @@ public class LockEliminationTest extends GraalCompilerTest { assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); } + public void testUnrolledSyncSnippet(Object a) { + for (int i = 0; i < 3; i++) { + synchronized (a) { + + } + } + } + + @Test + public void testUnrolledSync() { + StructuredGraph graph = getGraph("testUnrolledSyncSnippet"); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, new PhaseContext(getProviders())); + HighTierContext context = getDefaultHighTierContext(); + new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context); + new LockEliminationPhase().apply(graph); + assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); + } + private StructuredGraph getGraph(String snippet) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); StructuredGraph graph = parseEager(method, AllowAssumptions.YES); @@ -101,7 +121,6 @@ public class LockEliminationTest extends GraalCompilerTest { new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - new ValueAnchorCleanupPhase().apply(graph); new LockEliminationPhase().apply(graph); return graph; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java index 75c5d71b369..bf1a63b61e6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java @@ -24,15 +24,12 @@ package org.graalvm.compiler.core.test; import jdk.vm.ci.meta.JavaConstant; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Assert; import org.junit.Test; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; @@ -55,7 +52,7 @@ public class LongNodeChainTest extends GraalCompilerTest { private void longAddChain(boolean reverse) { HighTierContext context = getDefaultHighTierContext(); - StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).build(); ValueNode constant = graph.unique(ConstantNode.forPrimitive(JavaConstant.INT_1)); ValueNode value = null; if (reverse) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java new file mode 100644 index 00000000000..2b7923b814d --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java @@ -0,0 +1,97 @@ +/* + * 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.core.test; + +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugDumpScope; +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; + +public class LoopFullUnrollTest extends GraalCompilerTest { + + public static int testMinToMax(int input) { + int ret = 2; + int current = input; + for (long i = Long.MIN_VALUE; i < Long.MAX_VALUE; i++) { + ret *= 2 + current; + current /= 50; + } + return ret; + } + + @Test + public void runMinToMax() throws Throwable { + test("testMinToMax", 1); + } + + public static int testMinTo0(int input) { + int ret = 2; + int current = input; + for (long i = Long.MIN_VALUE; i <= 0; i++) { + ret *= 2 + current; + current /= 50; + } + return ret; + } + + @Test + public void runMinTo0() throws Throwable { + test("testMinTo0", 1); + } + + public static int testNegativeTripCount(int input) { + int ret = 2; + int current = input; + for (long i = 0; i <= -20; i++) { + ret *= 2 + current; + current /= 50; + } + return ret; + } + + @Test + public void runNegativeTripCount() throws Throwable { + test("testNegativeTripCount", 0); + } + + @SuppressWarnings("try") + private void test(String snippet, int loopCount) { + try (Scope s = Debug.scope(getClass().getSimpleName(), new DebugDumpScope(snippet))) { + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + + PhaseContext context = new PhaseContext(getProviders()); + new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); + + assertTrue(graph.getNodes().filter(LoopBeginNode.class).count() == loopCount); + } catch (Throwable e) { + throw Debug.handle(e); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java index ae12cbfd4dc..e4a74f9b4b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java @@ -28,12 +28,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; public class MemoryArithmeticTest extends GraalCompilerTest { @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - return getCode(method, graph, true); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + return super.getCode(method, graph, true, installAsDefault, options); } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java index 398fc133e0d..05346528ba7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -48,8 +48,7 @@ import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; @@ -89,6 +88,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { private static final Container container = new Container(); private static final List containerList = new ArrayList<>(); + private static final double LOOP_ENTRY_PROBABILITY = 0.9; /** * In this test the read should be scheduled before the write. @@ -165,7 +165,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { try { return container.a; } finally { - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; } else { @@ -190,7 +190,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { try { return container.a; } finally { - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; } else { @@ -213,7 +213,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { */ public static int testLoop3Snippet(int a) { int j = 0; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (i - container.a == 0) { break; } @@ -246,7 +246,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop5Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; @@ -272,13 +272,13 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop6Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; } else { bb--; - for (int j = 0; j < b; ++j) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { obj.hash = 3; } } @@ -301,15 +301,15 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop7Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; } else { bb--; - for (int k = 0; k < a; ++k) { + for (int k = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, k < a); ++k) { if (k % 2 == 1) { - for (int j = 0; j < b; ++j) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { obj.hash = 3; } } @@ -333,12 +333,12 @@ public class MemoryScheduleTest extends GraphScheduleTest { */ public static int testLoop8Snippet(int a, int b) { int result = container.a; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; break; } else { - for (int j = 0; j < b; j++) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); j++) { container.a = 0; } } @@ -378,25 +378,6 @@ public class MemoryScheduleTest extends GraphScheduleTest { Assert.assertEquals(0, readBlock.getLoopDepth()); } - /** - * Here the read should float to the end (into the same block as the return). - */ - public static int testArrayCopySnippet(Integer intValue, char[] a, char[] b, int len) { - System.arraycopy(a, 0, b, 0, len); - return intValue.intValue(); - } - - @Test - public void testArrayCopy() { - ScheduleResult schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES); - StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); - assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count()); - ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first(); - assertTrue(ret.result() + " should be a FloatingReadNode", ret.result() instanceof FloatingReadNode); - assertDeepEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result())); - assertReadWithinAllReturnBlocks(schedule, true); - } - /** * Here the read should not float to the end. */ @@ -644,7 +625,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop4Snippet(int count) { int[] a = new int[count]; - for (int i = 0; i < a.length; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a.length); i++) { a[i] = i; } @@ -652,7 +633,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { int iwrap = count - 1; int sum = 0; - while (i < count) { + while (GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < count)) { sum += (a[i] + a[iwrap]) / 2; iwrap = i; i++; @@ -723,34 +704,33 @@ public class MemoryScheduleTest extends GraphScheduleTest { @SuppressWarnings("try") private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { - final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + OptionValues options = new OptionValues(getInitialOptions(), OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, options); try (Scope d = Debug.scope("FloatingReadTest", graph)) { - try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) { - HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - canonicalizer.apply(graph, context); - if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { - new InliningPhase(canonicalizer).apply(graph, context); - } - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { - graph.clearAllStateAfter(); - } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after removal of framestates"); - - new FloatingReadPhase().apply(graph); - new RemoveValueProxyPhase().apply(graph); - - MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); - new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); - - SchedulePhase schedule = new SchedulePhase(schedulingStrategy); - schedule.apply(graph); - assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); - return graph.getLastSchedule(); + HighTierContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, context); + if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + new InliningPhase(canonicalizer).apply(graph, context); } + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + graph.clearAllStateAfter(); + } + Debug.dump(Debug.BASIC_LEVEL, graph, "after removal of framestates"); + + new FloatingReadPhase().apply(graph); + new RemoveValueProxyPhase().apply(graph); + + MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); + new GuardLoweringPhase().apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); + + SchedulePhase schedule = new SchedulePhase(schedulingStrategy); + schedule.apply(graph); + assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); + return graph.getLastSchedule(); } catch (Throwable e) { throw Debug.handle(e); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java index 15a682de023..d3a294b77ef 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java @@ -61,7 +61,7 @@ public class MergeCanonicalizerTest extends GraalCompilerTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java index 458227396f4..79e06a498c9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java @@ -31,7 +31,10 @@ import org.junit.Test; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.test.AddExports; +// Export needed to open String.value field to reflection by this test +@AddExports("java.base/java.lang") public final class MethodHandleEagerResolution extends GraalCompilerTest { private static final MethodHandle FIELD_HANDLE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NarrowingReadTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NarrowingReadTest.java new file mode 100644 index 00000000000..859b9856719 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NarrowingReadTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.junit.Test; + +/** + * Sometimes it's possible to emit a smaller read from a larger memory location instead reading the + * whole thing and truncating it. Make sure it returns the right value. + */ +public class NarrowingReadTest extends GraalCompilerTest { + + public byte testNarrowReadSnippetByte(Long l) { + return (byte) l.longValue(); + } + + @Test + public void testNarrowReadByte() { + test("testNarrowReadSnippetByte", Long.valueOf(Byte.MAX_VALUE)); + } + + public short testNarrowReadSnippetShort(Long l) { + return (short) l.longValue(); + } + + @Test + public void testNarrowReadShort() { + test("testNarrowReadSnippetShort", Long.valueOf(Short.MAX_VALUE)); + } + + public int testNarrowReadSnippetInt(Long l) { + return (int) l.longValue(); + } + + @Test + public void testNarrowReadInt() { + test("testNarrowReadSnippetInt", Long.valueOf(Integer.MAX_VALUE)); + } + + public long testNarrowReadSnippetIntToLong(Long l) { + return (int) l.longValue(); + } + + @Test + public void testNarrowReadIntToLong() { + test("testNarrowReadSnippetIntToLong", Long.valueOf(Integer.MAX_VALUE)); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java index 543bb442408..b513695c592 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java @@ -142,7 +142,7 @@ public class NestedLoopTest extends GraalCompilerTest { private void test(String snippet, int rootExits, int nestedExits, int innerExits) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); Assert.assertEquals(3, cfg.getLoops().size()); @@ -162,7 +162,7 @@ public class NestedLoopTest extends GraalCompilerTest { Assert.assertEquals(rootExits, rootLoop.getExits().size()); Assert.assertEquals(nestedExits, nestedLoop.getExits().size()); Assert.assertEquals(innerExits, innerMostLoop.getExits().size()); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); } private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java index ee5ca6685a8..60ca82597f4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.Node; @@ -35,13 +32,14 @@ import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase.CustomCanonicalizer; import org.graalvm.compiler.phases.contract.NodeCostUtil; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; public class NodePropertiesTest extends GraalCompilerTest { @@ -58,9 +56,11 @@ public class NodePropertiesTest extends GraalCompilerTest { x = 2; sideEffect = null; } + int b = 4; sideEffect = null; + int c = b % 5; // can shift - return a * x * 4; + return a * x * c; } public static int test2Snippet(int a) { @@ -74,7 +74,7 @@ public class NodePropertiesTest extends GraalCompilerTest { } sideEffect = null; // cannot shift - return a * x * 3; + return a * x * 41; } public static final int ITERATIONS_LOOP_1 = 128; @@ -145,9 +145,8 @@ public class NodePropertiesTest extends GraalCompilerTest { } public static int arrayStoreTest(int a) { - String s = String.valueOf(a); - array[2] = s; - return s.length(); + array[2] = a; + return a; } public static int fieldLoad(int a) { @@ -162,10 +161,10 @@ public class NodePropertiesTest extends GraalCompilerTest { @Test public void testCanonicalizationExample() { HighTierContext htc = getDefaultHighTierContext(); - ImprovementSavingCanonicalizer c1 = new ImprovementSavingCanonicalizer(htc.getNodeCostProvider()); + ImprovementSavingCanonicalizer c1 = new ImprovementSavingCanonicalizer(); StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("test1Snippet")); new CanonicalizerPhase(c1).apply(g1, htc); - ImprovementSavingCanonicalizer c2 = new ImprovementSavingCanonicalizer(htc.getNodeCostProvider()); + ImprovementSavingCanonicalizer c2 = new ImprovementSavingCanonicalizer(); StructuredGraph g2 = parseForCompile(getResolvedJavaMethod("test2Snippet")); new CanonicalizerPhase(c2).apply(g2, htc); Assert.assertTrue(c1.savedCycles > c2.savedCycles); @@ -249,7 +248,7 @@ public class NodePropertiesTest extends GraalCompilerTest { gc2.apply(g2, htc); Debug.log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); - Assert.assertTrue(gc2.finalSize == gc1.finalSize + 1/* mul has 3 const input */); + Assert.assertTrue(gc2.finalSize == gc1.finalSize); } @Test @@ -268,7 +267,7 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(35, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } @Test @@ -278,7 +277,7 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(50, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } @Test @@ -288,7 +287,7 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(30, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } @Test @@ -298,16 +297,11 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(120, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } static class ImprovementSavingCanonicalizer extends CustomCanonicalizer { private int savedCycles; - private final NodeCostProvider nodeCostProvider; - - ImprovementSavingCanonicalizer(NodeCostProvider nodeCostProvider) { - this.nodeCostProvider = nodeCostProvider; - } @Override public void simplify(Node node, SimplifierTool tool) { @@ -316,7 +310,7 @@ public class NodePropertiesTest extends GraalCompilerTest { Canonicalizable.Binary bc = (Canonicalizable.Binary) node; Node canonicalized = bc.canonical(tool, bc.getX(), bc.getY()); if (canonicalized != node) { - savedCycles += nodeCostProvider.getEstimatedCPUCycles(node) - nodeCostProvider.getEstimatedCPUCycles(canonicalized); + savedCycles += node.estimatedNodeCycles().value - canonicalized.estimatedNodeCycles().value; } } } @@ -328,8 +322,8 @@ public class NodePropertiesTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph, PhaseContext context) { - finalCycles = NodeCostUtil.computeGraphCycles(graph, context.getNodeCostProvider(), true); - finalSize = NodeCostUtil.computeGraphSize(graph, context.getNodeCostProvider()); + finalCycles = NodeCostUtil.computeGraphCycles(graph, true); + finalSize = NodeCostUtil.computeGraphSize(graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java index ccd10019b0d..a0091273103 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java @@ -41,12 +41,12 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.ServiceLoader; import java.util.Set; import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.test.GraalTest; import org.junit.Test; import org.objectweb.asm.ClassReader; @@ -57,7 +57,7 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; /** - * Verifies a class declaring one or more {@linkplain OptionValue options} has a class initializer + * Verifies a class declaring one or more {@linkplain OptionKey options} has a class initializer * that only initializes the option(s). This sanity check mitigates the possibility of an option * value being used before being set. */ @@ -67,7 +67,7 @@ public class OptionsVerifierTest { public void verifyOptions() throws IOException { try (Classpath cp = new Classpath()) { HashSet> checked = new HashSet<>(); - for (OptionDescriptors opts : ServiceLoader.load(OptionDescriptors.class, getClass().getClassLoader())) { + for (OptionDescriptors opts : OptionsParser.getOptionsLoader()) { for (OptionDescriptor desc : opts) { OptionsVerifier.checkClass(desc.getDeclaringClass(), desc, checked, cp); } @@ -257,7 +257,7 @@ public class OptionsVerifierTest { private boolean checkInvokeTarget(Executable method) { Class holder = method.getDeclaringClass(); if (method instanceof Constructor) { - if (OptionValue.class.isAssignableFrom(holder)) { + if (OptionKey.class.isAssignableFrom(holder)) { return true; } } else if (Arrays.asList(boxingTypes).contains(holder)) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java index b5101a9fcdd..7e6b7cc7142 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java @@ -70,7 +70,7 @@ public class PhiCreationTests extends GraalCompilerTest { @Test public void test3() { StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -86,7 +86,7 @@ public class PhiCreationTests extends GraalCompilerTest { @Test public void test4() { StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java index 9cfacabc7b8..3b07d6a8053 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java @@ -26,6 +26,7 @@ import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaType; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.graalvm.compiler.debug.Debug; @@ -42,7 +43,6 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.PushThroughPiPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; public class PushNodesThroughPiTest extends GraalCompilerTest { @@ -72,6 +72,7 @@ public class PushNodesThroughPiTest extends GraalCompilerTest { return ret; } + @Ignore @Test @SuppressWarnings("try") public void test1() { @@ -105,7 +106,6 @@ public class PushNodesThroughPiTest extends GraalCompilerTest { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new PushThroughPiPhase().apply(graph); canonicalizer.apply(graph, context); return graph; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java index 04cacfacff0..bdba9d022c1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java @@ -59,7 +59,7 @@ public class PushThroughIfTest extends GraalCompilerTest { private void test(String snippet, String reference) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java index 57ca56a6aae..8c1ef3d8f45 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java @@ -36,7 +36,6 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.OptimizeGuardAnchorsPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; /* consider @@ -93,10 +92,9 @@ public class ReadAfterCheckCastTest extends GraphScheduleTest { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); - new OptimizeGuardAnchorsPhase().apply(graph); canonicalizer.apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering"); + Debug.dump(Debug.BASIC_LEVEL, graph, "After lowering"); for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) { // Checking that the parameter a is not directly used for the access to field diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java index 6596d4d22c5..b4737bfb441 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java @@ -242,7 +242,7 @@ public class ReentrantBlockIteratorTest extends GraalCompilerTest { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, false); ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); // schedule for IGV - new SchedulePhase().apply(graph); + new SchedulePhase(graph.getOptions()).apply(graph); return blocks; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java index ff37a85e7ff..22b7b3f7676 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java @@ -27,14 +27,13 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import org.junit.Test; - -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopsData; 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.vm.ci.meta.ResolvedJavaField; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java new file mode 100644 index 00000000000..3f83a26ce07 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java @@ -0,0 +1,127 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +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.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; + +/** + * An implementation of {@link OptionDescriptor} that uses reflection to create descriptors from a + * list of field name and help text pairs. We cannot use the {@link Option} annotation as it has a + * {@link RetentionPolicy#SOURCE} retention policy. + * + * This class is useful for working with {@link OptionKey} and {@link OptionValues} but without + * having to rely on {@link Option} and its associated annotation processor. + */ +public class ReflectionOptionDescriptors implements OptionDescriptors { + + /** + * Extracts name/value entries from a set of properties based on a given name prefix. + * + * @param properties the properties set to extract from + * @param prefix entries whose names start with this prefix are extracted + * @param stripPrefix specifies whether to remove the prefix from the names in the returned map + */ + public static EconomicMap extractEntries(Properties properties, String prefix, boolean stripPrefix) { + EconomicMap matches = EconomicMap.create(); + for (Map.Entry e : properties.entrySet()) { + String name = (String) e.getKey(); + if (name.startsWith(prefix)) { + String value = (String) e.getValue(); + if (stripPrefix) { + name = name.substring(prefix.length()); + } + matches.put(name, value); + } + } + return matches; + } + + private final EconomicMap descriptors = EconomicMap.create(); + + public ReflectionOptionDescriptors(Class declaringClass, String... fieldsAndHelp) { + assert fieldsAndHelp.length % 2 == 0; + for (int i = 0; i < fieldsAndHelp.length; i += 2) { + String fieldName = fieldsAndHelp[i]; + String help = fieldsAndHelp[i + 1]; + addOption(declaringClass, fieldName, help); + } + } + + public ReflectionOptionDescriptors(Class declaringClass, EconomicMap fieldsAndHelp) { + MapCursor cursor = fieldsAndHelp.getEntries(); + while (cursor.advance()) { + String fieldName = cursor.getKey(); + String help = cursor.getValue(); + addOption(declaringClass, fieldName, help); + } + } + + private void addOption(Class declaringClass, String fieldName, String help) { + try { + Field f = declaringClass.getDeclaredField(fieldName); + if (!OptionKey.class.isAssignableFrom(f.getType())) { + throw new IllegalArgumentException(String.format("Option field must be of type %s: %s", OptionKey.class.getName(), f)); + } + if (!Modifier.isStatic(f.getModifiers())) { + throw new IllegalArgumentException(String.format("Option field must be static: %s", f)); + } + f.setAccessible(true); + Type declaredType = f.getAnnotatedType().getType(); + if (!(declaredType instanceof ParameterizedType)) { + throw new IllegalArgumentException(String.format("Option field must have a parameterized type: %s", f)); + } + 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))); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public Iterator iterator() { + return descriptors.getValues().iterator(); + } + + @Override + public OptionDescriptor get(String value) { + return descriptors.get(value); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java index da59e9c7235..040961c9836 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java @@ -131,7 +131,7 @@ public class ScalarTypeSystemTest extends GraalCompilerTest { private void test(final String snippet, final String referenceSnippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); new CanonicalizerPhase().apply(graph, context); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java index 22cbe45ca72..d61d92b59c2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java @@ -69,7 +69,7 @@ public class SchedulingTest2 extends GraphScheduleTest { BeginNode beginNode = graph.add(new BeginNode()); returnNode.replaceAtPredecessor(beginNode); beginNode.setNext(returnNode); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java index f750ecd1d49..746a145041c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Assert; import org.junit.Test; @@ -43,12 +41,12 @@ import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; public class SimpleCFGTest extends GraalCompilerTest { private static void dumpGraph(final StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); } @Test public void testImplies() { - StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).build(); EndNode trueEnd = graph.add(new EndNode()); EndNode falseEnd = graph.add(new EndNode()); @@ -109,7 +107,13 @@ public class SimpleCFGTest extends GraalCompilerTest { } public static void assertDominatedSize(Block block, int size) { - Assert.assertEquals("number of dominated blocks of " + block, size, block.getDominated().size()); + int count = 0; + Block domChild = block.getFirstDominated(); + while (domChild != null) { + count++; + domChild = domChild.getDominatedSibling(); + } + Assert.assertEquals("number of dominated blocks of " + block, size, count); } public static void assertPostdominator(Block block, Block expectedPostdominator) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java new file mode 100644 index 00000000000..5cbd3a3434b --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java @@ -0,0 +1,56 @@ +/* + * 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.core.test; + +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; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MemoryAccessProvider; + +/** + * + */ +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); + } + + @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); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java index 27af889f90a..a88f9e7cbdc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java @@ -22,27 +22,20 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; import java.lang.reflect.Method; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assume; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.DelegatingDebugConfig; 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; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase; @@ -50,6 +43,11 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; 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; /** * Test that interfaces are correctly initialized by a static field resolution during eager graph @@ -92,7 +90,7 @@ public class StaticInterfaceFieldTest extends GraalTest { final Method m = getMethod(clazz, methodName); ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("GraphBuilding", graph, method)) { graphBuilderSuite.apply(graph, context); } catch (Throwable e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java index 6c9dd26fcb8..dd754978ef8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java @@ -88,7 +88,7 @@ public class StraighteningTest extends GraalCompilerTest { private void test(final String snippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java index 2dc0a53fe30..67fd0d8b3f8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java @@ -28,10 +28,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; @@ -44,9 +40,12 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; /** * In the following tests, the scalar type system of the compiler should be complete enough to see @@ -180,18 +179,18 @@ public class TypeSystemTest extends GraalCompilerTest { private void test(String snippet, String referenceSnippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); /* * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, * tail-duplication gets activated thus resulting in a graph with more nodes than the * reference graph. */ - new DominatorConditionalEliminationPhase(false).apply(graph, new PhaseContext(getProviders())); + new ConditionalEliminationPhase(false).apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); // a second canonicalizer is needed to process nested MaterializeNodes new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); - new DominatorConditionalEliminationPhase(false).apply(referenceGraph, new PhaseContext(getProviders())); + new ConditionalEliminationPhase(false).apply(referenceGraph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); assertEquals(referenceGraph, graph); @@ -200,15 +199,15 @@ public class TypeSystemTest extends GraalCompilerTest { @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "expected (node count)"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "graph (node count)"); + Debug.dump(Debug.BASIC_LEVEL, expected, "expected (node count)"); + Debug.dump(Debug.BASIC_LEVEL, graph, "graph (node count)"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); } } public static void outputGraph(StructuredGraph graph, String message) { TTY.println("========================= " + message); - SchedulePhase schedulePhase = new SchedulePhase(); + SchedulePhase schedulePhase = new SchedulePhase(graph.getOptions()); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); for (Block block : schedule.getCFG().getBlocks()) { @@ -244,7 +243,7 @@ public class TypeSystemTest extends GraalCompilerTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph " + snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java index e6e6249aff8..6b44e9c7a97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java @@ -123,7 +123,7 @@ public class TypeWriterTest extends GraalCompilerTest { UnsafeArrayTypeWriter writer = UnsafeArrayTypeWriter.create(supportsUnalignedMemoryAccess); putValues(writer); - byte[] array = new byte[(int) writer.getBytesWritten()]; + byte[] array = new byte[TypeConversion.asU4(writer.getBytesWritten())]; writer.toArray(array); UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(array, 0, supportsUnalignedMemoryAccess); checkValues(reader); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java index 633441b981d..8ffd5090cdb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java @@ -22,24 +22,20 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.junit.Test; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - -import org.junit.Test; - -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; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.phases.OptimisticOptimizations; +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Exercise handling of unbalanced monitor operations by the parser. Algorithmically Graal assumes @@ -49,12 +45,16 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; * handle this directly is simplifying for targets of Graal since they don't have to provide a data * flow that checks this property. */ -public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes { +public class UnbalancedMonitorsTest extends GraalCompilerTest { private static final String CLASS_NAME = UnbalancedMonitorsTest.class.getName(); private static final String INNER_CLASS_NAME = CLASS_NAME + "$UnbalancedMonitors"; private static final String CLASS_NAME_INTERNAL = CLASS_NAME.replace('.', '/'); private static final String INNER_CLASS_NAME_INTERNAL = INNER_CLASS_NAME.replace('.', '/'); + public UnbalancedMonitorsTest() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + } + private static AsmLoader LOADER = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); @Test @@ -85,7 +85,7 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes private void checkForBailout(String name) throws ClassNotFoundException { ResolvedJavaMethod method = getResolvedJavaMethod(LOADER.findClass(INNER_CLASS_NAME), name); try { - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); Plugins plugins = new Plugins(new InvocationPlugins()); GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; @@ -101,6 +101,8 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes assertTrue("should have bailed out", false); } + static class Gen implements Opcodes { + // @formatter:off // Template class used with Bytecode Outline to generate ASM code // public static class UnbalancedMonitors { @@ -134,165 +136,167 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes // } // @formatter:on - public static byte[] generateClass() { + public static byte[] generateClass() { - ClassWriter cw = new ClassWriter(0); + ClassWriter cw = new ClassWriter(0); - cw.visit(52, ACC_SUPER | ACC_PUBLIC, INNER_CLASS_NAME_INTERNAL, null, "java/lang/Object", null); + cw.visit(52, ACC_SUPER | ACC_PUBLIC, INNER_CLASS_NAME_INTERNAL, null, "java/lang/Object", null); - cw.visitSource("UnbalancedMonitorsTest.java", null); + cw.visitSource("UnbalancedMonitorsTest.java", null); - cw.visitInnerClass(INNER_CLASS_NAME_INTERNAL, CLASS_NAME_INTERNAL, "UnbalancedMonitors", ACC_STATIC); + cw.visitInnerClass(INNER_CLASS_NAME_INTERNAL, CLASS_NAME_INTERNAL, "UnbalancedMonitors", ACC_STATIC); - visitConstructor(cw); - visitWrongOrder(cw); - visitBlockStructured(cw, true, false); - visitBlockStructured(cw, true, true); - visitBlockStructured(cw, false, false); - visitBlockStructured(cw, false, true); - cw.visitEnd(); + visitConstructor(cw); + visitWrongOrder(cw); + visitBlockStructured(cw, true, false); + visitBlockStructured(cw, true, true); + visitBlockStructured(cw, false, false); + visitBlockStructured(cw, false, true); + cw.visitEnd(); - return cw.toByteArray(); - } + return cw.toByteArray(); + } - private static void visitBlockStructured(ClassWriter cw, boolean normalReturnError, boolean tooMany) { - String name = (tooMany ? "tooMany" : "tooFew") + "Exits" + (normalReturnError ? "" : "Exceptional"); - // Generate too many or too few exits down the either the normal or exceptional return paths - int exceptionalExitCount = normalReturnError ? 1 : (tooMany ? 2 : 0); - int normalExitCount = normalReturnError ? (tooMany ? 2 : 0) : 1; - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, name, "(Ljava/lang/Object;Ljava/lang/Object;)Z", null, null); - mv.visitCode(); - Label l0 = new Label(); - Label l1 = new Label(); - Label l2 = new Label(); - mv.visitTryCatchBlock(l0, l1, l2, null); - Label l3 = new Label(); - mv.visitTryCatchBlock(l2, l3, l2, null); - Label l4 = new Label(); - Label l5 = new Label(); - Label l6 = new Label(); - mv.visitTryCatchBlock(l4, l5, l6, null); - Label l7 = new Label(); - mv.visitTryCatchBlock(l2, l7, l6, null); - Label l8 = new Label(); - mv.visitLabel(l8); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 3); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l4); - mv.visitVarInsn(ALOAD, 2); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 4); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l1); - for (int i = 0; i < normalExitCount; i++) { + private static void visitBlockStructured(ClassWriter cw, boolean normalReturnError, boolean tooMany) { + String name = (tooMany ? "tooMany" : "tooFew") + "Exits" + (normalReturnError ? "" : "Exceptional"); + // Generate too many or too few exits down the either the normal or exceptional return + // paths + int exceptionalExitCount = normalReturnError ? 1 : (tooMany ? 2 : 0); + int normalExitCount = normalReturnError ? (tooMany ? 2 : 0) : 1; + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, name, "(Ljava/lang/Object;Ljava/lang/Object;)Z", null, null); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, null); + Label l3 = new Label(); + mv.visitTryCatchBlock(l2, l3, l2, null); + Label l4 = new Label(); + Label l5 = new Label(); + Label l6 = new Label(); + mv.visitTryCatchBlock(l4, l5, l6, null); + Label l7 = new Label(); + mv.visitTryCatchBlock(l2, l7, l6, null); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 3); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l4); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 4); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l1); + for (int i = 0; i < normalExitCount; i++) { + mv.visitVarInsn(ALOAD, 3); + mv.visitInsn(MONITOREXIT); + } + mv.visitLabel(l5); + mv.visitInsn(IRETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", + "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l3); + mv.visitInsn(ATHROW); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, + new Object[]{"java/lang/Throwable"}); + for (int i = 0; i < exceptionalExitCount; i++) { + mv.visitVarInsn(ALOAD, 3); + mv.visitInsn(MONITOREXIT); + } + mv.visitLabel(l7); + mv.visitInsn(ATHROW); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitMaxs(2, 5); + mv.visitEnd(); + } + + private static void visitWrongOrder(ClassWriter cw) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "wrongOrder", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, null); + Label l3 = new Label(); + mv.visitTryCatchBlock(l2, l3, l2, null); + Label l4 = new Label(); + Label l5 = new Label(); + Label l6 = new Label(); + mv.visitTryCatchBlock(l4, l5, l6, null); + Label l7 = new Label(); + mv.visitTryCatchBlock(l2, l7, l6, null); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 3); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l4); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 4); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(MONITOREXIT); - } - mv.visitLabel(l5); - mv.visitInsn(IRETURN); - mv.visitLabel(l2); - mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", - "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l3); - mv.visitInsn(ATHROW); - mv.visitLabel(l6); - mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, - new Object[]{"java/lang/Throwable"}); - for (int i = 0; i < exceptionalExitCount; i++) { + mv.visitLabel(l1); + // Swapped exit order with exit above + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l5); + mv.visitInsn(ARETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", + "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l3); + mv.visitInsn(ATHROW); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, + new Object[]{"java/lang/Throwable"}); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(MONITOREXIT); + mv.visitLabel(l7); + mv.visitInsn(ATHROW); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitMaxs(2, 5); + mv.visitEnd(); } - mv.visitLabel(l7); - mv.visitInsn(ATHROW); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(2, 5); - mv.visitEnd(); - } - private static void visitWrongOrder(ClassWriter cw) { - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, "wrongOrder", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null); - mv.visitCode(); - Label l0 = new Label(); - Label l1 = new Label(); - Label l2 = new Label(); - mv.visitTryCatchBlock(l0, l1, l2, null); - Label l3 = new Label(); - mv.visitTryCatchBlock(l2, l3, l2, null); - Label l4 = new Label(); - Label l5 = new Label(); - Label l6 = new Label(); - mv.visitTryCatchBlock(l4, l5, l6, null); - Label l7 = new Label(); - mv.visitTryCatchBlock(l2, l7, l6, null); - Label l8 = new Label(); - mv.visitLabel(l8); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 3); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l4); - mv.visitVarInsn(ALOAD, 2); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 4); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 3); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l1); - // Swapped exit order with exit above - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l5); - mv.visitInsn(ARETURN); - mv.visitLabel(l2); - mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", - "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l3); - mv.visitInsn(ATHROW); - mv.visitLabel(l6); - mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, - new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 3); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l7); - mv.visitInsn(ATHROW); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(2, 5); - mv.visitEnd(); - } - - private static void visitConstructor(ClassWriter cw) { - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitInsn(RETURN); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitMaxs(1, 1); - mv.visitEnd(); + private static void visitConstructor(ClassWriter cw) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitInsn(RETURN); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } } public static class AsmLoader extends ClassLoader { @@ -308,7 +312,7 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes if (loaded != null) { return loaded; } - byte[] bytes = generateClass(); + byte[] bytes = Gen.generateClass(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java index 7e8914b2991..7e685a24492 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java @@ -22,11 +22,6 @@ */ package org.graalvm.compiler.core.test; -import java.lang.reflect.Field; - -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -34,27 +29,19 @@ import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Test; import sun.misc.Unsafe; public class UnsafeReadEliminationTest extends GraalCompilerTest { - public static final Unsafe UNSAFE; - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("Exception while trying to get Unsafe", e); - } - } - public static long[] Memory = new long[]{1, 2}; public static double SideEffectD; public static double SideEffectL; @@ -129,15 +116,16 @@ public class UnsafeReadEliminationTest extends GraalCompilerTest { } public void testPartialEscapeReadElimination(StructuredGraph graph, int reads, int writes) { + OptionValues options = graph.getOptions(); PhaseContext context = getDefaultHighTierContext(); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); canonicalizer.apply(graph, context); - new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context); + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); Assert.assertEquals(3, graph.getNodes().filter(UnsafeAccessNode.class).count()); // after lowering the same applies for reads and writes new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context); + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); Assert.assertEquals(reads, graph.getNodes().filter(ReadNode.class).count()); Assert.assertEquals(writes, graph.getNodes().filter(WriteNode.class).count()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java new file mode 100644 index 00000000000..236be5cff40 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java @@ -0,0 +1,94 @@ +/* + * 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.test; + +import java.lang.reflect.Field; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Test; + +public class UnsafeVirtualizationTest extends GraalCompilerTest { + + public static class A { + int f1; + int f2; + } + + private static final long AF1Offset; + private static final long AF2Offset; + static { + long o1 = -1; + long o2 = -1; + try { + Field f1 = A.class.getDeclaredField("f1"); + Field f2 = A.class.getDeclaredField("f2"); + o1 = UNSAFE.objectFieldOffset(f1); + o2 = UNSAFE.objectFieldOffset(f2); + } catch (NoSuchFieldException | SecurityException e) { + throw new AssertionError(e); + } + AF1Offset = o1; + AF2Offset = o2; + } + + public static int unsafeSnippet0(int i1, int i2) { + A a = new A(); + UNSAFE.putDouble(a, AF1Offset, i1 + i2); + return UNSAFE.getInt(a, AF1Offset) + UNSAFE.getInt(a, AF2Offset); + } + + public static int unsafeSnippet1(int i1, int i2) { + A a = new A(); + UNSAFE.putDouble(a, AF1Offset, i1 + i2); + a.f2 = i1; + return (int) UNSAFE.getDouble(a, AF1Offset); + } + + @Test + public void testUnsafePEA01() { + testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), false); + testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), true); + } + + @Test + public void testUnsafePEA02() { + testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), false); + testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), true); + } + + public void testPartialEscapeReadElimination(StructuredGraph graph, boolean canonicalizeBefore) { + OptionValues options = graph.getOptions(); + PhaseContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + if (canonicalizeBefore) { + canonicalizer.apply(graph, context); + } + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java new file mode 100644 index 00000000000..273d1404b18 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isEmpty; +import static org.junit.Assert.assertThat; + +import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.java.NewArrayNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; + +public class UnusedArray extends GraalCompilerTest { + @SuppressWarnings("unused") + public void smallArray() { + byte[] array = new byte[3]; + } + + @SuppressWarnings("unused") + public void largeArray() { + byte[] array = new byte[10 * 1024 * 1024]; + } + + @SuppressWarnings("unused") + public void unknownArray(int l) { + byte[] array = new byte[l]; + } + + @Test + public void testSmall() { + test("smallArray"); + } + + @Test + public void testLarge() { + test("largeArray"); + } + + @Test + public void testUnknown() { + test("unknownArray"); + } + + public void test(String method) { + StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.YES); + new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); + NodeIterable newArrayNodes = graph.getNodes().filter(NewArrayNode.class); + assertThat(newArrayNodes, isEmpty()); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java index ff82e1aabf2..20e4a5a1ba6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -30,14 +30,13 @@ import java.lang.reflect.Modifier; import org.junit.Test; import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.common.RetryableBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.RetryableBailoutException; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.GraalError; 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; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -129,7 +128,7 @@ public class VerifyBailoutUsageTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyBailoutUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java index 47aba0895c8..c0b45eddd7b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -37,7 +37,6 @@ import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.graph.Node; 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; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -84,9 +83,28 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph.toString()); + Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph.toString()); + } + } + + private static class InvalidDumpLevelPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + Debug.dump(Debug.VERY_DETAILED_LEVEL + 1, graph, "%s", graph); + } + } + + private static class NonConstantDumpLevelPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + Debug.dump(getLevel(), graph, "%s", graph); } + int getLevel() { + return 10; + } } private static class InvalidVerifyUsagePhase extends Phase { @@ -127,7 +145,7 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "error " + graph); + Debug.dump(Debug.BASIC_LEVEL, graph, "error " + graph); } } @@ -170,7 +188,7 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph); + Debug.dump(Debug.BASIC_LEVEL, graph, "%s", graph); } } @@ -187,7 +205,7 @@ public class VerifyDebugUsageTest { private static class InvalidGraalErrorGuaranteePhase extends Phase { @Override protected void run(StructuredGraph graph) { - GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s %s %s", graph, graph, graph, graph.toString()); + GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s %s %s", graph, graph, graph.toString()); } } @@ -234,6 +252,16 @@ public class VerifyDebugUsageTest { testDebugUsageClass(InvalidDumpUsagePhase.class); } + @Test(expected = VerificationError.class) + public void testDumpLevelInvalid() { + testDebugUsageClass(InvalidDumpLevelPhase.class); + } + + @Test(expected = VerificationError.class) + public void testDumpNonConstantLevelInvalid() { + testDebugUsageClass(NonConstantDumpLevelPhase.class); + } + @Test(expected = VerificationError.class) public void testLogInvalidConcat() { testDebugUsageClass(InvalidConcatLogUsagePhase.class); @@ -307,7 +335,7 @@ public class VerifyDebugUsageTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyDebugUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java index 0b6669b70a5..fb0ee2d59a8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; @@ -40,7 +40,6 @@ import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -274,7 +273,7 @@ public class VerifyVirtualizableTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyVirtualizableUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java index daa6e062861..b3eba89f26d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java @@ -91,8 +91,8 @@ public class AllocatorTest extends BackendTest { private void collectStats(final LIRInstruction instr) { instr.forEachOutput(collectStatsProc); - if (instr instanceof ValueMoveOp) { - ValueMoveOp move = (ValueMoveOp) instr; + if (ValueMoveOp.isValueMoveOp(instr)) { + ValueMoveOp move = ValueMoveOp.asValueMoveOp(instr); Value def = move.getResult(); Value use = move.getInput(); if (ValueUtil.isRegister(def)) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java index 5f689224d48..486420bc279 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java @@ -45,12 +45,12 @@ public abstract class BackendTest extends GraalCompilerTest { @SuppressWarnings("try") protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) { try (Scope s = Debug.scope("FrontEnd")) { - GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), getSuites()); + GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), createSuites(graph.getOptions())); } catch (Throwable e) { throw Debug.handle(e); } - LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, getLIRSuites()); + LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); return lirGen; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java index 5704e05f80b..5186169b13f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java @@ -26,7 +26,6 @@ import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -36,7 +35,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; - +import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; @@ -63,8 +62,7 @@ import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.calc.ShiftNode; import org.graalvm.compiler.nodes.calc.SignedDivNode; import org.graalvm.compiler.nodes.calc.SubNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; @@ -241,30 +239,26 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { static DebugConfig overrideGraalDebugConfig(PrintStream log, String methodFilter, String methodMeter) { List dumpHandlers = new ArrayList<>(); List verifyHandlers = new ArrayList<>(); + OptionValues options = getInitialOptions(); GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), - GraalDebugConfig.Options.Count.getValue(), - GraalDebugConfig.Options.TrackMemUse.getValue(), - GraalDebugConfig.Options.Time.getValue(), - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), + options, + GraalDebugConfig.Options.Log.getValue(options), + GraalDebugConfig.Options.Count.getValue(options), + GraalDebugConfig.Options.TrackMemUse.getValue(options), + GraalDebugConfig.Options.Time.getValue(options), + GraalDebugConfig.Options.Dump.getValue(options), + GraalDebugConfig.Options.Verify.getValue(options), methodFilter, methodMeter, log, dumpHandlers, verifyHandlers); return debugConfig; } - private static OverrideScope overrideMetricPrinterConfig() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - abstract Phase additionalPhase(); @Override - protected Suites createSuites() { - Suites ret = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites ret = super.createSuites(options); ListIterator> iter = ret.getHighTier().findPhase(ConvertDeoptimizeToGuardPhase.class, true); PhaseSuite.findNextPhase(iter, CanonicalizerPhase.class); iter.add(additionalPhase()); @@ -274,7 +268,7 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { @Test @SuppressWarnings("try") public void test() throws Throwable { - try (DebugConfigScope s = Debug.setConfig(getConfig()); OverrideScope o = getOScope();) { + try (DebugConfigScope s = Debug.setConfig(getConfig())) { executeMethod(TestApplication.class.getMethod("m01", testSignature), null, testArgs); executeMethod(TestApplication.class.getMethod("m02", testSignature), null, testArgs); executeMethod(TestApplication.class.getMethod("m03", testSignature), null, testArgs); @@ -289,6 +283,11 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { } } + void executeMethod(Method m, Object receiver, Object... args) { + OptionValues options = new OptionValues(getInitialOptions(), MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); + test(options, asResolvedJavaMethod(m), receiver, args); + } + @Before public void rememberScopeId() { scopeIdBeforeAccess = DebugScope.getCurrentGlobalScopeId(); @@ -301,10 +300,6 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { abstract DebugConfig getConfig(); - OverrideScope getOScope() { - return overrideMetricPrinterConfig(); - } - abstract void assertValues() throws Throwable; @SuppressWarnings("unchecked") @@ -312,7 +307,7 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { Map threadLocalMap = null; for (Field f : MethodMetricsImpl.class.getDeclaredFields()) { if (f.getName().equals("threadEntries")) { - f.setAccessible(true); + Util.setAccessible(f, true); Object map; try { map = ((ThreadLocal) f.get(null)).get(); @@ -373,9 +368,4 @@ public abstract class MethodMetricsTest extends GraalCompilerTest { throw new RuntimeException(t); } } - - void executeMethod(Method m, Object receiver, Object... args) { - test(asResolvedJavaMethod(m), receiver, args); - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java index ba51364d087..fdb9704e712 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java @@ -23,9 +23,7 @@ package org.graalvm.compiler.core.test.debug; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.Test; @@ -43,9 +41,7 @@ import org.graalvm.compiler.debug.internal.CounterImpl; import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; import org.graalvm.compiler.debug.internal.TimerImpl; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -62,26 +58,21 @@ public class MethodMetricsTestInterception01 extends MethodMetricsTest { DebugConfig getConfig() { List dumpHandlers = new ArrayList<>(); List verifyHandlers = new ArrayList<>(); + OptionValues options = getInitialOptions(); GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), + options, + GraalDebugConfig.Options.Log.getValue(options), "CountingAddPhase", - GraalDebugConfig.Options.TrackMemUse.getValue(), + GraalDebugConfig.Options.TrackMemUse.getValue(options), "CountingAddPhase", - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), + GraalDebugConfig.Options.Dump.getValue(options), + GraalDebugConfig.Options.Verify.getValue(options), "MethodMetricsTest$TestApplication.*", "CountingAddPhase", System.out, dumpHandlers, verifyHandlers); return debugConfig; } - @Override - protected OverrideScope getOScope() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - private DebugValueFactory factory; @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java index e00c2c89b25..af0d01c7961 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java @@ -23,9 +23,7 @@ package org.graalvm.compiler.core.test.debug; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; import org.junit.Test; @@ -42,9 +40,7 @@ import org.graalvm.compiler.debug.DebugValueFactory; import org.graalvm.compiler.debug.DebugVerifyHandler; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -127,13 +123,6 @@ public class MethodMetricsTestInterception02 extends MethodMetricsTest { }); } - @Override - protected OverrideScope getOScope() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - @Test @Override public void test() throws Throwable { @@ -151,13 +140,15 @@ public class MethodMetricsTestInterception02 extends MethodMetricsTest { DebugConfig getConfig() { List dumpHandlers = new ArrayList<>(); List verifyHandlers = new ArrayList<>(); + OptionValues options = getInitialOptions(); GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), + options, + GraalDebugConfig.Options.Log.getValue(options), ""/* unscoped meter */, - GraalDebugConfig.Options.TrackMemUse.getValue(), + GraalDebugConfig.Options.TrackMemUse.getValue(options), ""/* unscoped time */, - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), + GraalDebugConfig.Options.Dump.getValue(options), + GraalDebugConfig.Options.Verify.getValue(options), null /* no method filter */, "" /* unscoped method metering */, System.out, dumpHandlers, verifyHandlers); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java index 69826384295..d357e9feacb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java @@ -22,13 +22,11 @@ */ package org.graalvm.compiler.core.test.debug; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; @@ -36,7 +34,6 @@ import org.graalvm.compiler.debug.DebugMethodMetrics; import org.graalvm.compiler.graph.Node; 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; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -48,6 +45,7 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyDebugUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -256,7 +254,7 @@ public class VerifyMethodMetricsTest { for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); graphBuilderSuite.apply(graph, context); try (DebugConfigScope s = Debug.disableIntercept()) { new VerifyDebugUsage().apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java new file mode 100644 index 00000000000..a38400057b5 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java @@ -0,0 +1,77 @@ +/* + * 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.core.test.deopt; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.FrameState; +import org.junit.Test; + +public final class RethrowDeoptMaterializeTest extends GraalCompilerTest { + + private static final Object RETURN_VALUE = "1 2 3"; + private static final RuntimeException DUMMY_EXCEPTION = new RuntimeException(); + + static class MyException extends RuntimeException { + private static final long serialVersionUID = 0L; + + MyException(Throwable cause) { + super(cause); + } + + @SuppressWarnings("sync-override") + @Override + public final Throwable fillInStackTrace() { + return null; + } + } + + public static Object executeDeoptRethrow(int action) { + + try { + if (action != 0) { + throw new MyException(DUMMY_EXCEPTION); + } else if (action == 1) { + throw new MyException(null); + } + } catch (RuntimeException t) { + Throwable e = t.getCause(); + GraalDirectives.deoptimize(); + if (e != DUMMY_EXCEPTION) { + throw t; + } + } + return RETURN_VALUE; + } + + /** + * This tests that a state with {@link FrameState#rethrowException()} set to true can properly + * throw an exception that must be rematerialized. + */ + @Test + public void testDeoptRethrow() { + test("executeDeoptRethrow", 1); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java index 6ac8dd399ec..a5fa7f07f8f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java @@ -66,7 +66,7 @@ public final class SafepointRethrowDeoptTest extends GraalCompilerTest { @Test public void test() { - Assume.assumeTrue(GraalOptions.GenLoopSafepoints.getValue()); + Assume.assumeTrue(GraalOptions.GenLoopSafepoints.getValue(getInitialOptions())); synchronized (SafepointRethrowDeoptTest.class) { // needs static fields terminate = 1; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java index 735da745498..6be1e45f8d6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java @@ -160,7 +160,7 @@ public class EATestBase extends GraalCompilerTest { new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase().apply(graph, context); - new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null).apply(graph, context); + new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot(); } catch (Throwable e) { throw Debug.handle(e); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java index ebb431f5c3d..3af2ec92d7c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,21 +22,26 @@ */ package org.graalvm.compiler.core.test.ea; -import jdk.vm.ci.meta.JavaConstant; - -import org.junit.Assert; -import org.junit.Test; +import java.util.List; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ReturnNode; +import org.graalvm.compiler.nodes.extended.BoxNode; import org.graalvm.compiler.nodes.extended.ValueAnchorNode; +import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.JavaConstant; /** * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct @@ -179,6 +184,50 @@ public class EscapeAnalysisTest extends EATestBase { return obj.x <= 3 ? 1 : 0; } + @Test + public void testMergeAllocationsInt2() { + testEscapeAnalysis("testMergeAllocationsInt2Snippet", JavaConstant.forInt(1), true); + } + + public int testMergeAllocationsInt2Snippet(int a) { + /* + * The initial object in obj exists until the end of the function, but it can still be + * merged with the one allocated in the else block because noone can observe the identity. + */ + TestClassInt obj = new TestClassInt(1, 2); + if (a < 0) { + notInlineable(); + } else { + obj = new TestClassInt(1, 2); + notInlineable(); + } + return obj.x <= 3 ? 1 : 0; + } + + @Test + public void testMergeAllocationsInt3() { + // ensure that the result is not constant: + assertTrue(testMergeAllocationsInt3Snippet(true)); + assertFalse(testMergeAllocationsInt3Snippet(false)); + + prepareGraph("testMergeAllocationsInt3Snippet", true); + assertFalse(graph.getNodes().filter(ReturnNode.class).first().result().isConstant()); + } + + public boolean testMergeAllocationsInt3Snippet(boolean a) { + TestClassInt phi1; + TestClassInt phi2; + if (a) { + field = new TestClassObject(); + field = new TestClassObject(); + phi1 = phi2 = new TestClassInt(1, 2); + } else { + phi1 = new TestClassInt(2, 3); + phi2 = new TestClassInt(3, 4); + } + return phi1 == phi2; + } + @Test public void testMergeAllocationsObj() { testEscapeAnalysis("testMergeAllocationsObjSnippet", JavaConstant.forInt(1), false); @@ -259,9 +308,73 @@ public class EscapeAnalysisTest extends EATestBase { return obj.value <= 3 ? 1 : 0; } + /** + * Tests that a graph with allocations that does not make progress during PEA will not be + * changed. + */ + @Test + public void testChangeHandling() { + prepareGraph("testChangeHandlingSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + Assert.assertEquals(1, graph.getNodes().filter(BoxNode.class).count()); + List nodes = graph.getNodes().snapshot(); + // verify that an additional run doesn't add or remove nodes + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(nodes.size(), graph.getNodeCount()); + for (Node node : nodes) { + Assert.assertTrue(node.isAlive()); + } + } + + public volatile Object field; + + public int testChangeHandlingSnippet(int a) { + Object obj; + Integer one = 1; + obj = new MyException(one); + if (a < 0) { + notInlineable(); + } else { + obj = new Integer(1); + notInlineable(); + } + field = obj; + return 1; + } + + /** + * Test the case where allocations before and during a loop that have no usages other than their + * phi need to be recognized as an important change. This needs a loop so that the allocation is + * not trivially removed by dead code elimination. + */ + @Test + public void testRemovalSpecialCase() { + prepareGraph("testRemovalSpecialCaseSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + // create the situation by removing the if + graph.replaceFixedWithFloating(graph.getNodes().filter(LoadFieldNode.class).first(), graph.unique(ConstantNode.forInt(0))); + new CanonicalizerPhase().apply(graph, context); + // verify that an additional run removes all allocations + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count()); + } + + public volatile int field2; + + public int testRemovalSpecialCaseSnippet(int a) { + Object phi = new Object(); + for (int i = 0; i < a; i++) { + field = null; + if (field2 == 1) { + phi = new Object(); + } + } + return phi == null ? 1 : 0; + } + @Test public void testCheckCast() { - testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), false); + testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), true); } public Object testCheckCastSnippet() { @@ -314,7 +427,7 @@ public class EscapeAnalysisTest extends EATestBase { public void testFullyUnrolledLoop() { prepareGraph("testFullyUnrolledLoopSnippet", false); new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); Assert.assertEquals(1, returnNodes.size()); Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode); CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit(); @@ -345,7 +458,7 @@ public class EscapeAnalysisTest extends EATestBase { public void testPeeledLoop() { prepareGraph("testPeeledLoopSnippet", false); new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, getDefaultHighTierContext()); - new SchedulePhase().apply(graph); + new SchedulePhase(graph.getOptions()).apply(graph); } public static void testDeoptMonitorSnippetInner(Object o2, Object t, int i) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java index 94ca53834f6..c42c6f001d3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java @@ -28,7 +28,7 @@ import sun.misc.Unsafe; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; @@ -130,7 +130,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe1() { StructuredGraph graph = processMethod("testUnsafe1Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } public static int testUnsafe2Snippet(int v, Object array) { @@ -143,7 +143,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe2() { StructuredGraph graph = processMethod("testUnsafe2Snippet", false); - assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count()); } private static final long offsetObject1 = Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * 1; @@ -159,7 +159,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe3() { StructuredGraph graph = processMethod("testUnsafe3Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } public static int testUnsafe4Snippet(int v, Object[] array) { @@ -173,7 +173,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe4() { StructuredGraph graph = processMethod("testUnsafe4Snippet", false); - assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count()); } private static final long offsetLong1 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 1; @@ -189,7 +189,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe5() { StructuredGraph graph = processMethod("testUnsafe5Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } @Override @@ -197,7 +197,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - new PartialEscapePhase(false, true, new CanonicalizerPhase(), null).apply(graph, context); + new PartialEscapePhase(false, true, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); return graph; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java index 206ee38c0e4..becd415971a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java @@ -135,6 +135,7 @@ public class PartialEscapeAnalysisTest extends EATestBase { } public static Object[] array = new Object[]{1, 2, 3, 4, 5, "asdf", "asdf"}; + public static char[] charArray = new char[]{1, 2, 3, 4, 5, 'a', 'f'}; public static Object testArrayCopySnippet(int a) { Object[] tmp = new Object[]{a != 1 ? array[a] : null}; @@ -143,6 +144,18 @@ public class PartialEscapeAnalysisTest extends EATestBase { return tmp2[4]; } + @Test + public void testPrimitiveArraycopy() { + testPartialEscapeAnalysis("testPrimitiveArraycopySnippet", 0, 0); + } + + public static Object testPrimitiveArraycopySnippet(int a) { + char[] tmp = new char[]{a != 1 ? charArray[a] : 0}; + char[] tmp2 = new char[5]; + System.arraycopy(tmp, 0, tmp2, 4, 1); + return tmp2[4]; + } + @Test @Ignore public void testCache() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java index 2c558b1d247..79a744ecbb3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java @@ -244,10 +244,10 @@ public class InliningTest extends GraalCompilerTest { ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)) : getDefaultGraphBuilderSuite(); HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + Debug.dump(Debug.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java new file mode 100644 index 00000000000..8a386ea2eed --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java @@ -0,0 +1,154 @@ +/* + * 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.test.inlining; + +import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.phases.BasePhase; +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.InliningUtil; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; +import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.graalvm.util.EconomicSet; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; +import sun.misc.Unsafe; + +public class NestedLoopEffectsPhaseComplexityTest extends GraalCompilerTest { + + public static int IntSideEffect; + public static int[] Memory = new int[]{0}; + + public static void recursiveLoopMethodUnsafeLoad(int a) { + if (UNSAFE.getInt(Memory, (long) Unsafe.ARRAY_INT_BASE_OFFSET) == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethodUnsafeLoad(i); + } + } + + public static void recursiveLoopMethodFieldLoad(int a) { + if (IntSideEffect == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethodFieldLoad(i); + } + } + + public static void recursiveLoopMethod(int a) { + if (a == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethod(i); + } + } + + private static final boolean LOG_PHASE_TIMINGS = false; + private static int InliningCountLowerBound = 1; + private static int InliningCountUpperBound = 32; + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallUnsafeLoad() { + testAndTime("recursiveLoopMethodUnsafeLoad"); + } + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallFieldLoad() { + testAndTime("recursiveLoopMethodFieldLoad"); + } + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallNoReads() { + testAndTime("recursiveLoopMethod"); + } + + private void testAndTime(String snippet) { + initializeForTimeout(); + for (int i = InliningCountLowerBound; i < InliningCountUpperBound; i++) { + StructuredGraph g1 = prepareGraph(snippet, i); + StructuredGraph g2 = (StructuredGraph) g1.copy(); + ResolvedJavaMethod method = g1.method(); + long elapsedRE = runAndTimePhase(g1, new EarlyReadEliminationPhase(new CanonicalizerPhase())); + long elapsedPEA = runAndTimePhase(g2, new PartialEscapePhase(true, new CanonicalizerPhase(), g1.getOptions())); + if (LOG_PHASE_TIMINGS) { + TTY.printf("Needed %dms to run early partial escape analysis on a graph with %d nested loops compiling method %s\n", elapsedPEA, i, method); + } + if (LOG_PHASE_TIMINGS) { + TTY.printf("Needed %dms to run early read elimination on a graph with %d nested loops compiling method %s\n", elapsedRE, i, method); + } + } + } + + private long runAndTimePhase(StructuredGraph g, BasePhase phase) { + HighTierContext context = getDefaultHighTierContext(); + long start = System.currentTimeMillis(); + phase.apply(g, context); + long end = System.currentTimeMillis(); + Debug.dump(Debug.DETAILED_LEVEL, g, "After %s", phase.contractorName()); + return end - start; + } + + private StructuredGraph prepareGraph(String snippet, int inliningCount) { + ResolvedJavaMethod callerMethod = getResolvedJavaMethod(snippet); + StructuredGraph callerGraph = parseEager(callerMethod, AllowAssumptions.YES); + PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite(); + HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + Invoke next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); + StructuredGraph calleeGraph = parseBytecodes(next.callTarget().targetMethod(), context, canonicalizer); + ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod(); + for (int i = 0; i < inliningCount; i++) { + next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); + EconomicSet canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod); + canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); + Debug.dump(Debug.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); + } + return callerGraph; + } + + private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer) { + StructuredGraph newGraph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.NO).method(method).build(); + context.getGraphBuilderSuite().apply(newGraph, context); + new DeadCodeEliminationPhase(Optional).apply(newGraph); + canonicalizer.apply(newGraph, context); + return newGraph; + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java deleted file mode 100644 index 4e1d784d4a4..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java +++ /dev/null @@ -1,206 +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.test.inlining; - -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -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.InliningUtil; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; -import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; -import sun.misc.Unsafe; - -public class RecursiveInliningTest extends GraalCompilerTest { - - public static int SideEffectI; - public static int[] Memory = new int[]{1, 2}; - - public static final Unsafe UNSAFE; - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("Exception while trying to get Unsafe", e); - } - } - - public static void recursiveLoopMethodUnsafeLoad(int a) { - if (UNSAFE.getInt(Memory, (long) Unsafe.ARRAY_LONG_BASE_OFFSET) == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethodUnsafeLoad(i); - } - } - - public static void recursiveLoopMethodFieldLoad(int a) { - if (SideEffectI == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethodFieldLoad(i); - } - } - - public static void recursiveLoopMethod(int a) { - if (a == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethod(i); - } - } - - public static final boolean LOG = false; - - public static int IterationsStart = 1; - public static int IterationsEnd = 128; - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallUnsafeLoad() { - testAndTime("recursiveLoopMethodUnsafeLoad"); - } - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallFieldLoad() { - testAndTime("recursiveLoopMethodFieldLoad"); - } - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallNoReads() { - testAndTime("recursiveLoopMethod"); - } - - private void testAndTime(String snippet) { - for (int i = IterationsStart; i < IterationsEnd; i++) { - StructuredGraph graph = getGraph(snippet, i); - long elapsed = runAndTimeEarlyReadEliminationPhase(graph); - if (LOG) { - System.out.printf("Needed %dms to run early read elimination on a graph with %d recursive inlined calls of method %s\n", elapsed, i, graph.method()); - } - } - for (int i = IterationsStart; i < IterationsEnd; i++) { - StructuredGraph graph = getGraph(snippet, i); - long elapsed = runAndTimePartialEscapeAnalysis(graph); - if (LOG) { - System.out.printf("Needed %dms to run early partial escape analysis on a graph with %d recursive inlined calls of method %s\n", elapsed, i, graph.method()); - } - } - } - - private long runAndTimePartialEscapeAnalysis(StructuredGraph g) { - PartialEscapePhase p = new PartialEscapePhase(true, new CanonicalizerPhase()); - HighTierContext context = getDefaultHighTierContext(); - long start = System.currentTimeMillis(); - p.apply(g, context); - long end = System.currentTimeMillis(); - Debug.dump(Debug.BASIC_LOG_LEVEL, g, "After PEA"); - return end - start; - } - - private long runAndTimeEarlyReadEliminationPhase(StructuredGraph g) { - EarlyReadEliminationPhase er = new EarlyReadEliminationPhase(new CanonicalizerPhase()); - HighTierContext context = getDefaultHighTierContext(); - long start = System.currentTimeMillis(); - er.apply(g, context); - long end = System.currentTimeMillis(); - Debug.dump(Debug.BASIC_LOG_LEVEL, g, "After Early Read Elimination"); - return end - start; - } - - @SuppressWarnings("try") - private StructuredGraph getGraph(final String snippet, int nrOfInlinings) { - try (Scope s = Debug.scope("RecursiveInliningTest", new DebugDumpScope(snippet, true))) { - ResolvedJavaMethod callerMethod = getResolvedJavaMethod(snippet); - StructuredGraph callerGraph = parseEager(callerMethod, AllowAssumptions.YES); - PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite(); - HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - - for (int i = 0; i < nrOfInlinings; i++) { - InvokeNode next = getNextInvoke(callerGraph); - ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod(); - StructuredGraph calleeGraph = getInlineeGraph(next, callerGraph, context, canonicalizer); - List canonicalizeNodes = new ArrayList<>(); - InliningUtil.inline(next, calleeGraph, false, canonicalizeNodes, calleeMethod); - canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); - Debug.dump(Debug.BASIC_LOG_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); - } - new SchedulePhase().apply(callerGraph); - return callerGraph; - } catch (Throwable e) { - throw Debug.handle(e); - } - } - - private static StructuredGraph getInlineeGraph(InvokeNode invoke, StructuredGraph caller, HighTierContext context, CanonicalizerPhase canonicalizer) { - StructuredGraph result = InliningUtil.getIntrinsicGraph(context.getReplacements(), invoke.callTarget().targetMethod(), invoke.bci()); - if (result != null) { - return result; - } - return parseBytecodes(invoke.callTarget().targetMethod(), context, canonicalizer, caller); - } - - @SuppressWarnings("try") - private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { - StructuredGraph newGraph = new StructuredGraph(method, AllowAssumptions.from(caller.getAssumptions() != null), INVALID_COMPILATION_ID); - if (!caller.isUnsafeAccessTrackingEnabled()) { - newGraph.disableUnsafeAccessTracking(); - } - if (context.getGraphBuilderSuite() != null) { - context.getGraphBuilderSuite().apply(newGraph, context); - } - assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite " + method + ", " + method.canBeInlined(); - new DeadCodeEliminationPhase(Optional).apply(newGraph); - canonicalizer.apply(newGraph, context); - return newGraph; - } - - private static InvokeNode getNextInvoke(StructuredGraph graph) { - return graph.getNodes().filter(InvokeNode.class).first(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java index 815bb88a54a..7e7c166e81e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.core.test.tutorial; +import java.lang.reflect.Method; +import java.util.regex.Pattern; + +import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.junit.Assert; import org.junit.Test; -import org.graalvm.compiler.bytecode.Bytecode; -import org.graalvm.compiler.bytecode.BytecodeDisassembler; -import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; - import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -49,14 +49,31 @@ public class GraalTutorial extends InvokeGraal { */ @Test - public void testPrintBytecodes() { - ResolvedJavaMethod method = findMethod(String.class, "hashCode"); - Bytecode bytecode = new ResolvedJavaMethodBytecode(method); + public void testGetBytecodes() throws NoSuchMethodException { + Method reflectionMethod = String.class.getDeclaredMethod("hashCode"); + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(reflectionMethod); - byte[] bytecodes = bytecode.getCode(); - Assert.assertNotNull(bytecodes); + /* + * ResolvedJavaMethod provides all information that you want about a method, for example, + * the bytecodes. + */ + byte[] bytecodes = method.getCode(); - System.out.println(new BytecodeDisassembler().disassemble(bytecode)); + /* + * BytecodeDisassembler shows you how to iterate bytecodes, how to access type information, + * and more. + */ + String disassembly = new BytecodeDisassembler().disassemble(method); + + /* + * We don't want test cases to print any output, so we check the validity of the output + * instead. + */ + Pattern disassemblyLineRE = Pattern.compile(" *\\d+: [a-z][\\w_]+"); + for (String line : disassembly.split("\\n")) { + Assert.assertTrue(line, disassemblyLineRE.matcher(line).find()); + } + Assert.assertTrue(bytecodes.length > 0); } /* @@ -131,6 +148,21 @@ public class GraalTutorial extends InvokeGraal { * Tutorial example for snippets and lowering. */ + public static int identityHashCodeUsage(Object obj) { + return System.identityHashCode(obj); + } + + @Test + public void testIdentityHashCodeUsage() throws InvalidInstalledCodeException { + Object a = new Object(); + int expectedResult = identityHashCodeUsage(a); + + InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "identityHashCodeUsage")); + + int result = (int) compiledMethod.executeVarargs(a); + Assert.assertEquals(expectedResult, result); + } + static class A { } @@ -173,17 +205,18 @@ public class GraalTutorial extends InvokeGraal { * Tutorial example for intrinsic methods. */ - public static double intrinsicUsage(double val) { - return Math.sin(val); + public static int intrinsicIntegerReverseBytes(int val) { + return Integer.reverseBytes(val); } @Test - public void testIntrinsicUsage() throws InvalidInstalledCodeException { - double expectedResult = intrinsicUsage(42d); + public void testIntrinsicIntegerReverseBytes() throws InvalidInstalledCodeException { + int input = 0x12345678; + int expected = intrinsicIntegerReverseBytes(input); - InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicUsage")); + InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicIntegerReverseBytes")); - double result = (double) compiledMethod.executeVarargs(42d); - Assert.assertEquals(expectedResult, result, 0); + int actual = (int) compiledMethod.executeVarargs(input); + Assert.assertEquals(expected, actual); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java index c722047e256..66f5e038953 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.core.test.tutorial; import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCompilationRequest; - +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import org.graalvm.compiler.api.test.Graal; @@ -38,6 +38,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -83,6 +84,7 @@ public class InvokeGraal { protected InstalledCode compileAndInstallMethod(ResolvedJavaMethod method) { /* Create a unique compilation identifier, visible in IGV. */ CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); + OptionValues options = getInitialOptions(); try (Scope s = Debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) { /* @@ -91,7 +93,7 @@ public class InvokeGraal { * that we want the compilation to make optimistic assumptions about runtime state such * as the loaded class hierarchy. */ - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.YES, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).method(method).compilationId(compilationId).build(); /* * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If @@ -103,12 +105,12 @@ public class InvokeGraal { * The optimization phases that are applied to the graph. This is the main configuration * point for Graal. Add or remove phases to customize your compilation. */ - Suites suites = backend.getSuites().getDefaultSuites(); + Suites suites = backend.getSuites().getDefaultSuites(options); /* * The low-level phases that are applied to the low-level representation. */ - LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(); + LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(options); /* * We want Graal to perform all speculative optimistic optimizations, using the diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java index 4f8a61e1901..0f6e4cc21a6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test.tutorial; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.util.ArrayDeque; import java.util.Collections; @@ -45,7 +45,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; @@ -241,7 +240,7 @@ public class StaticAnalysis { * Build the Graal graph for the method using the bytecode parser provided by Graal. */ - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build(); /* * Support for graph dumping, IGV uses this information to show the method name of a * graph. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java index 26541c81573..9456485839d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java @@ -22,15 +22,12 @@ */ package org.graalvm.compiler.core; -import static org.graalvm.compiler.core.GraalCompilerOptions.EmitLIRRepeatCount; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; -import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; - import java.util.Collection; import java.util.List; 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.alloc.ComputeBlockOrder; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; @@ -41,9 +38,11 @@ import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.DebugTimer; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; -import org.graalvm.compiler.lir.BailoutAndRestartBackendException; import org.graalvm.compiler.lir.LIR; +import org.graalvm.compiler.lir.alloc.OutOfRegistersException; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.framemap.FrameMap; @@ -58,18 +57,16 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.options.OptionValue.OverrideScope; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; -import org.graalvm.compiler.phases.common.instrumentation.ExtractInstrumentationPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.TargetDescription; @@ -93,7 +90,6 @@ public class GraalCompiler { private static final DebugTimer BackEnd = Debug.timer("BackEnd"); private static final DebugTimer EmitLIR = Debug.timer("EmitLIR"); private static final DebugTimer EmitCode = Debug.timer("EmitCode"); - private static final LIRGenerationPhase LIR_GENERATION_PHASE = new LIRGenerationPhase(); /** * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}. @@ -172,7 +168,7 @@ public class GraalCompiler { @SuppressWarnings("try") public static T compile(Request r) { try (Scope s = MethodMetricsRootScopeInfo.createRootScopeIfAbsent(r.installedCodeOwner); - CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod()) { + CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { assert !r.graph.isFrozen(); try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start()) { emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); @@ -180,10 +176,41 @@ public class GraalCompiler { } catch (Throwable e) { throw Debug.handle(e); } + checkForRequestedCrash(r.graph); return r.compilationResult; } } + /** + * Checks whether the {@link GraalCompilerOptions#CrashAt} option indicates that the compilation + * of {@code graph} should result in an exception. + * + * @param graph a graph currently being compiled + * @throws RuntimeException if the value of {@link GraalCompilerOptions#CrashAt} matches + * {@code graph.method()} or {@code graph.name} + */ + private static void checkForRequestedCrash(StructuredGraph graph) { + String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions()); + if (methodPattern != null) { + String crashLabel = null; + if (graph.name != null && graph.name.contains(methodPattern)) { + crashLabel = graph.name; + } + if (crashLabel == null) { + ResolvedJavaMethod method = graph.method(); + MethodFilter[] filters = MethodFilter.parse(methodPattern); + for (MethodFilter filter : filters) { + if (filter.matches(method)) { + crashLabel = method.format("%H.%n(%p)"); + } + } + } + if (crashLabel != null) { + throw new RuntimeException("Forced crash after compiling " + crashLabel); + } + } + } + /** * Builds the graph, optimizes it. */ @@ -194,27 +221,30 @@ public class GraalCompiler { HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts); if (graph.start().next() == null) { graphBuilderSuite.apply(graph, highTierContext); - new DeadCodeEliminationPhase(Optional).apply(graph); + new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph); + Debug.dump(Debug.BASIC_LEVEL, graph, "After parsing"); } else { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "initial state"); - } - if (UseGraalInstrumentation.getValue()) { - new ExtractInstrumentationPhase().apply(graph, highTierContext); + Debug.dump(Debug.INFO_LEVEL, graph, "initial state"); } suites.getHighTier().apply(graph, highTierContext); graph.maybeCompress(); + Debug.dump(Debug.BASIC_LEVEL, graph, "After high tier"); MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo); suites.getMidTier().apply(graph, midTierContext); graph.maybeCompress(); + Debug.dump(Debug.BASIC_LEVEL, graph, "After mid tier"); LowTierContext lowTierContext = new LowTierContext(providers, target); suites.getLowTier().apply(graph, lowTierContext); + Debug.dump(Debug.BASIC_LEVEL, graph, "After low tier"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); + Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); } catch (Throwable e) { throw Debug.handle(e); + } finally { + graph.checkCancellation(); } } @@ -222,13 +252,6 @@ public class GraalCompiler { public static void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { try (Scope s = Debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start()) { - // Repeatedly run the LIR code generation pass to improve statistical profiling results. - for (int i = 0; i < EmitLIRRepeatCount.getValue(); i++) { - SchedulePhase dummySchedule = new SchedulePhase(); - dummySchedule.apply(graph); - emitLIR(backend, graph, stub, registerConfig, lirSuites); - } - LIRGenerationResult lirGen = null; lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites); try (Scope s2 = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { @@ -240,54 +263,44 @@ public class GraalCompiler { } } catch (Throwable e) { throw Debug.handle(e); + } finally { + graph.checkCancellation(); } } @SuppressWarnings("try") public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { - OverrideScope overrideScope = null; - LIRSuites lirSuites0 = lirSuites; - while (true) { - try (OverrideScope scope = overrideScope) { - return emitLIR0(backend, graph, stub, registerConfig, lirSuites0); - } catch (BailoutAndRestartBackendException e) { - if (BailoutAndRestartBackendException.Options.LIRUnlockBackendRestart.getValue() && e.shouldRestart()) { - overrideScope = e.getOverrideScope(); - lirSuites0 = e.updateLIRSuites(lirSuites); - if (lirSuites0 != null) { - continue; - } - } - /* - * The BailoutAndRestartBackendException is permanent. If restart fails or is - * disabled we throw the bailout. - */ - throw e; + String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); + String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); + try { + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); + } catch (OutOfRegistersException e) { + if (allocationRestrictedTo != null) { + allocationRestrictedTo = null; + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); } + /* If the re-execution fails we convert the exception into a "hard" failure */ + throw new GraalError(e); + } finally { + graph.checkCancellation(); } } @SuppressWarnings("try") - private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { + private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, + String[] allocationRestrictedTo) { try (Scope ds = Debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start()) { + assert !graph.hasValueProxies(); ScheduleResult schedule = graph.getLastSchedule(); Block[] blocks = schedule.getCFG().getBlocks(); Block startBlock = schedule.getCFG().getStartBlock(); assert startBlock != null; assert startBlock.getPredecessorCount() == 0; - LIR lir = null; - AbstractBlockBase[] codeEmittingOrder = null; - AbstractBlockBase[] linearScanOrder = null; - try (Scope s = Debug.scope("ComputeLinearScanOrder", lir)) { - codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); - linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); + AbstractBlockBase[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); + AbstractBlockBase[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); + LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions()); - lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After linear scan order"); - } catch (Throwable e) { - throw Debug.handle(e); - } FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig); LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub); LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes); @@ -295,18 +308,20 @@ public class GraalCompiler { // LIR generation LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); - LIR_GENERATION_PHASE.apply(backend.getTarget(), lirGenRes, context); + new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); - try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "After LIR generation"); - LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig)); - Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "Before code generation"); + try (Scope s = Debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { + // Dump LIR along with HIR (the LIR is looked up from context) + Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation"); + LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo)); return result; } catch (Throwable e) { throw Debug.handle(e); } } catch (Throwable e) { throw Debug.handle(e); + } finally { + graph.checkCancellation(); } } @@ -325,18 +340,21 @@ public class GraalCompiler { RegisterAllocationConfig registerAllocationConfig) { PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen); lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext); + Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext); + Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext); + Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); return lirGenRes; } @SuppressWarnings("try") - public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, Collection accessedFields, + public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, EconomicSet accessedFields, int bytecodeSize, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { try (DebugCloseable a = EmitCode.start()) { @@ -378,7 +396,7 @@ public class GraalCompiler { Debug.counter("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); } - Debug.dump(Debug.BASIC_LOG_LEVEL, compilationResult, "After code generation"); + Debug.dump(Debug.BASIC_LEVEL, compilationResult, "After code generation"); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java index f8c8a0a30ad..835a66276aa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java @@ -23,8 +23,8 @@ package org.graalvm.compiler.core; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; /** * Options related to {@link GraalCompiler}. @@ -32,22 +32,22 @@ import org.graalvm.compiler.options.OptionValue; public class GraalCompilerOptions { // @formatter:off - @Option(help = "Repeatedly run the LIR code generation pass to improve statistical profiling results.", type = OptionType.Debug) - public static final OptionValue EmitLIRRepeatCount = new OptionValue<>(0); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintFilter = new OptionValue<>(null); + public static final OptionKey PrintFilter = new OptionKey<>(null); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintCompilation = new OptionValue<>(false); + public static final OptionKey PrintCompilation = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintAfterCompilation = new OptionValue<>(false); + public static final OptionKey PrintAfterCompilation = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintBailout = new OptionValue<>(false); + public static final OptionKey PrintBailout = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ExitVMOnBailout = new OptionValue<>(false); + public static final OptionKey ExitVMOnBailout = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ExitVMOnException = new OptionValue<>(false); + public static final OptionKey ExitVMOnException = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintStackTraceOnException = new OptionValue<>(false); + public static final OptionKey PrintStackTraceOnException = new OptionKey<>(false); + @Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " + + "This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug) + public static final OptionKey CrashAt = new OptionKey<>(null); // @formatter:on - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java index 38cb71febee..b47db55b019 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.DebugInitializationParticipant; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.ServiceProvider; /** @@ -39,52 +40,57 @@ public class GraalDebugInitializationParticipant implements DebugInitializationP @Override public void apply(Params params) { - if (GraalDebugConfig.areDebugScopePatternsEnabled()) { + OptionValues options = params.getOptions(); + if (GraalDebugConfig.areDebugScopePatternsEnabled(options)) { params.enable = true; } - if ("".equals(GraalDebugConfig.Options.Count.getValue())) { + if ("".equals(GraalDebugConfig.Options.Count.getValue(options))) { params.enableUnscopedCounters = true; } - if ("".equals(GraalDebugConfig.Options.MethodMeter.getValue())) { + if ("".equals(GraalDebugConfig.Options.MethodMeter.getValue(options))) { params.enableUnscopedMethodMetrics = true; // mm requires full debugging support params.enable = true; } - if ("".equals(GraalDebugConfig.Options.Time.getValue())) { + if ("".equals(GraalDebugConfig.Options.Time.getValue(options))) { params.enableUnscopedTimers = true; } - if ("".equals(GraalDebugConfig.Options.TrackMemUse.getValue())) { + if ("".equals(GraalDebugConfig.Options.TrackMemUse.getValue(options))) { params.enableUnscopedMemUseTrackers = true; } // unscoped counters/timers/mem use trackers/method metrics should respect method filter // semantics if (!params.enable && (params.enableUnscopedMemUseTrackers || params.enableUnscopedMethodMetrics || params.enableUnscopedCounters || params.enableUnscopedTimers) && - GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodFilter)) { + GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodFilter, options)) { params.enable = true; params.enableMethodFilter = true; } - if (!params.enableUnscopedMethodMetrics && GraalDebugConfig.Options.MethodMeter.getValue() != null) { + if (!params.enable && GraalDebugConfig.Options.DumpOnPhaseChange.getValue(options) != null) { + params.enable = true; + } + + if (!params.enableUnscopedMethodMetrics && GraalDebugConfig.Options.MethodMeter.getValue(options) != null) { // mm requires full debugging support params.enable = true; } - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { + if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { if (!params.enable) { TTY.println("WARNING: MethodMeter is disabled but GlobalMetricsInterceptedByMethodMetrics is enabled. Ignoring MethodMeter and GlobalMetricsInterceptedByMethodMetrics."); } else { - parseMethodMetricsDebugValueInterception(params); + parseMethodMetricsDebugValueInterception(params, options); } } - if (GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodMeter) || params.enableUnscopedMethodMetrics) { - if (!MethodMetricsPrinter.methodMetricsDumpingEnabled()) { + if (GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodMeter, options) || params.enableUnscopedMethodMetrics) { + if (!MethodMetricsPrinter.methodMetricsDumpingEnabled(options)) { TTY.println("WARNING: MethodMeter is enabled but MethodMeter dumping is disabled. Output will not contain MethodMetrics."); } } } - private static void parseMethodMetricsDebugValueInterception(Params params) { - String interceptionGroup = GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.getValue(); + private static void parseMethodMetricsDebugValueInterception(Params params, OptionValues options) { + String interceptionGroup = GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.getValue(options); boolean intercepted = false; if (interceptionGroup.contains("Timers")) { params.interceptTime = true; @@ -101,7 +107,6 @@ public class GraalDebugInitializationParticipant implements DebugInitializationP if (!intercepted) { TTY.println("WARNING: Ignoring GlobalMetricsInterceptedByMethodMetrics as the supplied argument does not contain Timers/Counters/MemUseTrackers."); - GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.setValue(null); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java index 51aa28e0296..c20f8689a8f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java @@ -57,6 +57,7 @@ public class LIRGenerationPhase extends LIRPhase> blockMap) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java index 4449ecc3e7d..fea9c328d2a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java @@ -24,13 +24,11 @@ package org.graalvm.compiler.core.gen; import java.util.ArrayDeque; import java.util.Arrays; -import java.util.Map; import java.util.Queue; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LabelRef; @@ -44,9 +42,12 @@ import org.graalvm.compiler.nodes.virtual.EscapeObjectState; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.virtual.nodes.MaterializedObjectState; import org.graalvm.compiler.virtual.nodes.VirtualObjectState; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.VirtualObject; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.JavaValue; @@ -68,8 +69,8 @@ public class DebugInfoBuilder { private static final JavaValue[] NO_JAVA_VALUES = {}; private static final JavaKind[] NO_JAVA_KINDS = {}; - protected final Map virtualObjects = Node.newMap(); - protected final Map objectStates = Node.newIdentityMap(); + protected final EconomicMap virtualObjects = EconomicMap.create(Equivalence.IDENTITY); + protected final EconomicMap objectStates = EconomicMap.create(Equivalence.IDENTITY); protected final Queue pendingVirtualObjects = new ArrayDeque<>(); @@ -118,8 +119,13 @@ public class DebugInfoBuilder { assert currentField != null; int pos = 0; for (int i = 0; i < entryCount; i++) { - if (!currentField.values().get(i).isConstant() || currentField.values().get(i).asJavaConstant().getJavaKind() != JavaKind.Illegal) { - ValueNode value = currentField.values().get(i); + ValueNode value = currentField.values().get(i); + if (value == null) { + JavaKind entryKind = vobjNode.entryKind(i); + values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind()); + slotKinds[pos] = entryKind.getStackKind(); + pos++; + } else if (!value.isConstant() || value.asJavaConstant().getJavaKind() != JavaKind.Illegal) { values[pos] = toJavaValue(value); slotKinds[pos] = toSlotKind(value); pos++; @@ -137,7 +143,11 @@ public class DebugInfoBuilder { vobjValue.setValues(values, slotKinds); } - virtualObjectsArray = virtualObjects.values().toArray(new VirtualObject[virtualObjects.size()]); + virtualObjectsArray = new VirtualObject[virtualObjects.size()]; + int index = 0; + for (VirtualObject value : virtualObjects.getValues()) { + virtualObjectsArray[index++] = value; + } virtualObjects.clear(); } objectStates.clear(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java index 2c70da10cb2..d3f443ea1bc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java @@ -22,25 +22,23 @@ */ package org.graalvm.compiler.core.gen; -import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; -import static org.graalvm.compiler.lir.LIR.verifyBlock; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isLegal; import static jdk.vm.ci.code.ValueUtil.isRegister; +import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.lir.LIR.verifyBlock; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.match.ComplexMatchValue; +import org.graalvm.compiler.core.match.MatchPattern; import org.graalvm.compiler.core.match.MatchRuleRegistry; import org.graalvm.compiler.core.match.MatchStatement; import org.graalvm.compiler.debug.Debug; @@ -99,6 +97,9 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.NodeValueMap; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; @@ -117,6 +118,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio private final NodeMap nodeOperands; private final DebugInfoBuilder debugInfoBuilder; + private final int traceLIRGeneratorLevel; protected final LIRGenerator gen; @@ -124,16 +126,18 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio private ValueNode lastInstructionPrinted; // Debugging only private final NodeMatchRules nodeMatchRules; - private Map, List> matchRules; + private EconomicMap, List> matchRules; public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRules nodeMatchRules) { this.gen = (LIRGenerator) gen; this.nodeMatchRules = nodeMatchRules; this.nodeOperands = graph.createNodeMap(); this.debugInfoBuilder = createDebugInfoBuilder(graph, this); - if (MatchExpressions.getValue()) { - matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass()); + OptionValues options = graph.getOptions(); + if (MatchExpressions.getValue(options)) { + matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options); } + traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options); assert nodeMatchRules.lirBuilder == null; nodeMatchRules.lirBuilder = this; @@ -177,9 +181,10 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio @Override public ValueNode valueForOperand(Value value) { assert nodeOperands != null; - for (Entry entry : nodeOperands.entries()) { - if (entry.getValue().equals(value)) { - return (ValueNode) entry.getKey(); + UnmodifiableMapCursor cursor = nodeOperands.getEntries(); + while (cursor.advance()) { + if (cursor.getValue().equals(value)) { + return (ValueNode) cursor.getKey(); } } return null; @@ -206,7 +211,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio */ public void setMatchResult(Node x, Value operand) { assert operand.equals(ComplexMatchValue.INTERIOR_MATCH) || operand instanceof ComplexMatchValue; - assert operand instanceof ComplexMatchValue || x.getUsageCount() == 1 : "interior matches must be single user"; + assert operand instanceof ComplexMatchValue || MatchPattern.isSingleValueUser(x) : "interior matches must be single user"; assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice"; assert !(x instanceof VirtualObjectNode); nodeOperands.set(x, operand); @@ -227,7 +232,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } public final void append(LIRInstruction op) { - if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue(nodeOperands.graph().getOptions()) && !TTY.isSuppressed()) { if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { lastInstructionPrinted = currentInstruction; InstructionPrinter ip = new InstructionPrinter(TTY.out()); @@ -238,32 +243,27 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } protected LIRKind getExactPhiKind(PhiNode phi) { - // TODO (je): maybe turn this into generator-style instead of allocating an ArrayList. - ArrayList values = new ArrayList<>(phi.valueCount()); - for (int i = 0; i < phi.valueCount(); i++) { + LIRKind derivedKind = gen.toRegisterKind(gen.getLIRKind(phi.stamp())); + /* Collect reference information. */ + for (int i = 0; i < phi.valueCount() && !derivedKind.isUnknownReference(); i++) { ValueNode node = phi.valueAt(i); Value value = getOperand(node); + + // get ValueKind for input + final LIRKind valueKind; if (value != null) { - values.add(value.getValueKind(LIRKind.class)); + valueKind = value.getValueKind(LIRKind.class); } else { assert isPhiInputFromBackedge(phi, i) : String.format("Input %s to phi node %s is not yet available although it is not coming from a loop back edge", node, phi); - // non-java constant -> get LIRKind from stamp. LIRKind kind = gen.getLIRKind(node.stamp()); - values.add(gen.toRegisterKind(kind)); + valueKind = gen.toRegisterKind(kind); } + /* Merge the reference information of the derived kind and the input. */ + derivedKind = LIRKind.mergeReferenceInformation(derivedKind, valueKind); } - LIRKind derivedKind = LIRKind.merge(values); - assert verifyPHIKind(derivedKind, gen.getLIRKind(phi.stamp())); return derivedKind; } - private boolean verifyPHIKind(LIRKind derivedKind, LIRKind phiKind) { - PlatformKind derivedPlatformKind = derivedKind.getPlatformKind(); - PlatformKind phiPlatformKind = gen.toRegisterKind(phiKind).getPlatformKind(); - assert derivedPlatformKind.equals(phiPlatformKind) : "kinds don't match: " + derivedPlatformKind + " vs " + phiPlatformKind; - return true; - } - private static boolean isPhiInputFromBackedge(PhiNode phi, int index) { AbstractMergeNode merge = phi.merge(); AbstractEndNode end = merge.phiPredecessorAt(index); @@ -318,6 +318,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio @Override @SuppressWarnings("try") public void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap) { + + OptionValues options = graph.getOptions(); try (BlockScope blockScope = gen.getBlockScope(block)) { setSourcePosition(null); @@ -332,7 +334,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio AbstractMergeNode merge = (AbstractMergeNode) begin; LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0); label.setPhiValues(createPhiIn(merge)); - if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) { TTY.println("Created PhiIn: " + label); } @@ -345,11 +347,12 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio // of instructions matchComplexExpressions(nodes); + boolean trace = traceLIRGeneratorLevel >= 3; for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); if (node instanceof ValueNode) { ValueNode valueNode = (ValueNode) node; - if (Options.TraceLIRGeneratorLevel.getValue() >= 3) { + if (trace) { TTY.println("LIRGen for " + valueNode); } Value operand = getOperand(valueNode); @@ -401,7 +404,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio protected void matchComplexExpressions(List nodes) { if (matchRules != null) { try (Scope s = Debug.scope("MatchComplexExpressions")) { - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(nodeOperands.graph().getOptions())) { int i = 0; for (Node node : nodes) { Debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); @@ -432,7 +435,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio protected abstract boolean peephole(ValueNode valueNode); private void doRoot(ValueNode instr) { - if (Options.TraceLIRGeneratorLevel.getValue() >= 2) { + if (traceLIRGeneratorLevel >= 2) { TTY.println("Emitting LIR for instruction " + instr); } currentInstruction = instr; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java index 280b67041dc..2e281b6cdfe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java @@ -56,6 +56,8 @@ import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; @@ -87,6 +89,8 @@ import org.graalvm.compiler.nodes.memory.WriteNode; @MatchableNode(nodeClass = OrNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = XorNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = PiNode.class, inputs = {"object"}) +@MatchableNode(nodeClass = LogicCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) +@MatchableNode(nodeClass = ValueCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) public abstract class NodeMatchRules { NodeLIRBuilder lirBuilder; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java index 9abe43aefff..6d0a36e373a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java @@ -26,9 +26,7 @@ import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.Result; @@ -37,6 +35,8 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; /** * Container for state captured during a match. @@ -49,7 +49,7 @@ public class MatchContext { private final MatchStatement rule; - private Map namedNodes; + private EconomicMap namedNodes; private ArrayList consumed; @@ -85,7 +85,7 @@ public class MatchContext { public Result captureNamedValue(String name, Class type, Node value) { if (namedNodes == null) { - namedNodes = new HashMap<>(2); + namedNodes = EconomicMap.create(Equivalence.DEFAULT); } NamedNode current = namedNodes.get(name); if (current == null) { @@ -109,7 +109,7 @@ public class MatchContext { // don't interfere with this match. continue; } else if ((consumed == null || !consumed.contains(node)) && node != root) { - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(root.getOptions())) { Debug.log("unexpected node %s", node); for (int j = startIndex; j <= endIndex; j++) { Node theNode = nodes.get(j); @@ -151,7 +151,7 @@ public class MatchContext { * @return Result.OK if the node can be safely consumed. */ public Result consume(Node node) { - assert node.getUsageCount() <= 1 : "should have already been checked"; + assert MatchPattern.isSingleValueUser(node) : "should have already been checked"; // Check NOT_IN_BLOCK first since that usually implies ALREADY_USED int index = nodes.indexOf(node); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java index 171c2dbfc34..e3c60e37851 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java @@ -26,6 +26,7 @@ import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; /** @@ -252,7 +253,7 @@ public class MatchPattern { } if (singleUser && !atRoot) { - if (node.getUsageCount() > 1) { + if (!isSingleValueUser(node)) { return Result.tooManyUsers(node, statement.getPattern()); } } @@ -267,6 +268,31 @@ public class MatchPattern { return result; } + public static boolean isSingleValueUser(Node node) { + int valueUsage = node.getUsageCount(); + if (valueUsage == 1) { + return true; + } + if (node.isAllowedUsageType(InputType.Guard)) { + // See if the other usages are non-Value usages. + valueUsage = 0; + for (Node usage : node.usages()) { + for (Position input : usage.inputPositions()) { + if (input.getInputType() == InputType.Value && input.get(usage) == node) { + valueUsage++; + if (valueUsage > 1) { + // Too many value users + return false; + } + } + } + } + assert valueUsage == 1; + return true; + } + return false; + } + /** * For a node starting at root, produce a String showing the inputs that matched against this * rule. It's assumed that a match has already succeeded against this rule, otherwise the diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java index bab5c593b20..e595df33510 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java @@ -23,12 +23,8 @@ package org.graalvm.compiler.core.match; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; - import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.debug.Debug; @@ -38,7 +34,11 @@ import org.graalvm.compiler.graph.Edges; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; public class MatchRuleRegistry { @@ -67,30 +67,32 @@ public class MatchRuleRegistry { return result; } - private static final HashMap, Map, List>> registry = new HashMap<>(); + private static final EconomicMap, EconomicMap, List>> registry = EconomicMap.create(Equivalence.IDENTITY); /** * Collect all the {@link MatchStatement}s defined by the superclass chain of theClass. * * @param theClass + * @param options * @return the set of {@link MatchStatement}s applicable to theClass. */ @SuppressWarnings("try") - public static synchronized Map, List> lookup(Class theClass) { - Map, List> result = registry.get(theClass); + public static synchronized EconomicMap, List> lookup(Class theClass, OptionValues options) { + EconomicMap, List> result = registry.get(theClass); if (result == null) { - Map, List> rules = createRules(theClass); + EconomicMap, List> rules = createRules(theClass); registry.put(theClass, rules); assert registry.get(theClass) == rules; result = rules; - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(options)) { try (Scope s = Debug.scope("MatchComplexExpressions")) { Debug.log("Match rules for %s", theClass.getSimpleName()); - for (Entry, List> entry : result.entrySet()) { - Debug.log(" For node class: %s", entry.getKey()); - for (MatchStatement statement : entry.getValue()) { + MapCursor, List> cursor = result.getEntries(); + while (cursor.advance()) { + Debug.log(" For node class: %s", cursor.getKey()); + for (MatchStatement statement : cursor.getValue()) { Debug.log(" %s", statement.getPattern()); } } @@ -108,8 +110,9 @@ public class MatchRuleRegistry { * This is a separate, public method so that external clients can create rules with a custom * lookup and without the default caching behavior. */ - public static Map, List> createRules(Class theClass) { - HashMap, MatchStatementSet> matchSets = new HashMap<>(); + @SuppressWarnings("unchecked") + public static EconomicMap, List> createRules(Class theClass) { + EconomicMap, MatchStatementSet> matchSets = EconomicMap.create(Equivalence.IDENTITY); Iterable sl = GraalServices.load(MatchStatementSet.class); for (MatchStatementSet rules : sl) { matchSets.put(rules.forClass(), rules); @@ -117,8 +120,8 @@ public class MatchRuleRegistry { // Walk the class hierarchy collecting lists and merge them together. The subclass // rules are first which gives them preference over earlier rules. - Map, List> rules = new HashMap<>(); - Class currentClass = theClass; + EconomicMap, List> rules = EconomicMap.create(Equivalence.IDENTITY); + Class currentClass = theClass; do { MatchStatementSet matchSet = matchSets.get(currentClass); if (matchSet != null) { @@ -133,7 +136,7 @@ public class MatchRuleRegistry { current.add(statement); } } - currentClass = currentClass.getSuperclass(); + currentClass = (Class) currentClass.getSuperclass(); } while (currentClass != NodeMatchRules.class); return rules; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java index 7d4fbb0ae8c..80398efe8c4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java @@ -103,12 +103,12 @@ public class MatchStatement { } // The pattern matched but some other code generation constraint disallowed code // generation for the pattern. - if (LogVerbose.getValue()) { + if (LogVerbose.getValue(node.getOptions())) { Debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); Debug.log("with nodes %s", formatMatch(node)); } } else { - if (LogVerbose.getValue() && result.code != MatchResultCode.WRONG_CLASS) { + if (LogVerbose.getValue(node.getOptions()) && result.code != MatchResultCode.WRONG_CLASS) { Debug.log("while matching %s|%s %s %s", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), result); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java index c2ff09dff27..d714edea6a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAlloc 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; @@ -38,33 +39,32 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class CoreCompilerConfiguration implements CompilerConfiguration { @Override - public PhaseSuite createHighTier() { - return new HighTier(); + public PhaseSuite createHighTier(OptionValues options) { + return new HighTier(options); } @Override - public PhaseSuite createMidTier() { - return new MidTier(); + public PhaseSuite createMidTier(OptionValues options) { + return new MidTier(options); } @Override - public PhaseSuite createLowTier() { - return new LowTier(); + public PhaseSuite createLowTier(OptionValues options) { + return new LowTier(options); } @Override - public LIRPhaseSuite createPreAllocationOptimizationStage() { - return new PreAllocationOptimizationStage(); + public LIRPhaseSuite createPreAllocationOptimizationStage(OptionValues options) { + return new PreAllocationOptimizationStage(options); } @Override - public LIRPhaseSuite createAllocationStage() { - return new AllocationStage(); + public LIRPhaseSuite createAllocationStage(OptionValues options) { + return new AllocationStage(options); } @Override - public LIRPhaseSuite createPostAllocationOptimizationStage() { - return new PostAllocationOptimizationStage(); + public LIRPhaseSuite createPostAllocationOptimizationStage(OptionValues options) { + return new PostAllocationOptimizationStage(options); } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java index 307a59b3049..c7736b37223 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.lir.phases.EconomyPreAllocationOptimizationStage; import org.graalvm.compiler.lir.phases.LIRPhaseSuite; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +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; @@ -38,32 +39,32 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class EconomyCompilerConfiguration implements CompilerConfiguration { @Override - public PhaseSuite createHighTier() { - return new EconomyHighTier(); + public PhaseSuite createHighTier(OptionValues options) { + return new EconomyHighTier(options); } @Override - public PhaseSuite createMidTier() { - return new EconomyMidTier(); + public PhaseSuite createMidTier(OptionValues options) { + return new EconomyMidTier(options); } @Override - public PhaseSuite createLowTier() { - return new EconomyLowTier(); + public PhaseSuite createLowTier(OptionValues options) { + return new EconomyLowTier(options); } @Override - public LIRPhaseSuite createPreAllocationOptimizationStage() { + public LIRPhaseSuite createPreAllocationOptimizationStage(OptionValues options) { return new EconomyPreAllocationOptimizationStage(); } @Override - public LIRPhaseSuite createAllocationStage() { + public LIRPhaseSuite createAllocationStage(OptionValues options) { return new EconomyAllocationStage(); } @Override - public LIRPhaseSuite createPostAllocationOptimizationStage() { + public LIRPhaseSuite createPostAllocationOptimizationStage(OptionValues options) { return new EconomyPostAllocationOptimizationStage(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java index 76efa541752..fb4b35c5bef 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; @@ -32,9 +33,9 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; public class EconomyHighTier extends PhaseSuite { - public EconomyHighTier() { + public EconomyHighTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java index db1b0f11018..3950f8ead8a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; @@ -34,9 +35,9 @@ import org.graalvm.compiler.phases.tiers.LowTierContext; public class EconomyLowTier extends PhaseSuite { - public EconomyLowTier() { + public EconomyLowTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java index c6350bc2ffd..504bed773bc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; @@ -36,9 +37,9 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class EconomyMidTier extends PhaseSuite { - public EconomyMidTier() { + public EconomyMidTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } appendPhase(new RemoveValueProxyPhase()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java index bb7236d6ced..e54d37020c7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.phases; -import java.util.Set; -import java.util.stream.Collectors; - import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.graph.Graph.NodeEvent; @@ -36,6 +33,8 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicSet; /** * A utility phase for detecting when a phase would change the graph and reporting extra information @@ -77,24 +76,29 @@ public class GraphChangeMonitoringPhase extends PhaseSui Debug.handle(t); } } - /* - * Ignore LogicConstantNode since those are sometimes created and deleted as part of running - * a phase. - */ - if (listener.getNodes().stream().filter(e -> !(e instanceof LogicConstantNode)).findFirst().isPresent()) { + + EconomicSet filteredNodes = EconomicSet.create(Equivalence.IDENTITY); + for (Node n : listener.getNodes()) { + if (n instanceof LogicConstantNode) { + // Ignore LogicConstantNode since those are sometimes created and deleted as part of + // running a phase. + } else { + filteredNodes.add(n); + } + } + if (!filteredNodes.isEmpty()) { /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */ listener = new HashSetNodeEventListener(); try (NodeEventScope s = graph.trackNodeEvents(listener)) { try (Scope s2 = Debug.scope("WithGraphChangeMonitoring")) { - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** Before phase %s", getName()); + if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { + Debug.dump(Debug.DETAILED_LEVEL, graph, "*** Before phase %s", getName()); } super.run(graph, context); - Set collect = listener.getNodes().stream().filter(e -> !e.isAlive()).filter(e -> !(e instanceof LogicConstantNode)).collect(Collectors.toSet()); - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** After phase %s %s", getName(), collect); + if (Debug.isDumpEnabled(Debug.DETAILED_LEVEL)) { + Debug.dump(Debug.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes); } - Debug.log("*** %s %s %s\n", message, graph, collect); + Debug.log("*** %s %s %s\n", message, graph, filteredNodes); } } } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java index 675c1dd9d30..358d6cb0b4f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java @@ -29,8 +29,8 @@ import static org.graalvm.compiler.core.common.GraalOptions.LoopPeeling; import static org.graalvm.compiler.core.common.GraalOptions.LoopUnswitch; import static org.graalvm.compiler.core.common.GraalOptions.OptConvertDeoptsToGuards; import static org.graalvm.compiler.core.common.GraalOptions.OptLoopTransform; +import static org.graalvm.compiler.core.common.GraalOptions.OptReadElimination; import static org.graalvm.compiler.core.common.GraalOptions.PartialEscapeAnalysis; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; import org.graalvm.compiler.loop.DefaultLoopPolicies; @@ -40,8 +40,9 @@ import org.graalvm.compiler.loop.phases.LoopPeelingPhase; import org.graalvm.compiler.loop.phases.LoopUnswitchingPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; @@ -51,8 +52,8 @@ import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; -import org.graalvm.compiler.phases.common.instrumentation.HighTierReconcileInstrumentationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; public class HighTier extends PhaseSuite { @@ -61,57 +62,58 @@ public class HighTier extends PhaseSuite { // @formatter:off @Option(help = "Enable inlining", type = OptionType.Expert) - public static final OptionValue Inline = new OptionValue<>(true); + public static final OptionKey Inline = new OptionKey<>(true); // @formatter:on } - public HighTier() { + public HighTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } appendPhase(canonicalizer); - if (Options.Inline.getValue()) { + if (Options.Inline.getValue(options)) { appendPhase(new InliningPhase(canonicalizer)); appendPhase(new DeadCodeEliminationPhase(Optional)); - - if (ConditionalElimination.getValue()) { - appendPhase(canonicalizer); - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); - } } - if (OptConvertDeoptsToGuards.getValue()) { + if (OptConvertDeoptsToGuards.getValue(options)) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new ConvertDeoptimizeToGuardPhase())); } + if (ConditionalElimination.getValue(options)) { + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); + } + LoopPolicies loopPolicies = createLoopPolicies(); - if (FullUnroll.getValue()) { + if (FullUnroll.getValue(options)) { appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies)); } - if (OptLoopTransform.getValue()) { - if (LoopPeeling.getValue()) { + if (OptLoopTransform.getValue(options)) { + if (LoopPeeling.getValue(options)) { appendPhase(new LoopPeelingPhase(loopPolicies)); } - if (LoopUnswitch.getValue()) { + if (LoopUnswitch.getValue(options)) { appendPhase(new LoopUnswitchingPhase(loopPolicies)); } } appendPhase(canonicalizer); - if (PartialEscapeAnalysis.getValue()) { - appendPhase(new PartialEscapePhase(true, canonicalizer)); + if (PartialEscapeAnalysis.getValue(options)) { + appendPhase(new PartialEscapePhase(true, canonicalizer, options)); } + + if (OptReadElimination.getValue(options)) { + appendPhase(new EarlyReadEliminationPhase(canonicalizer)); + } + appendPhase(new RemoveValueProxyPhase()); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new HighTierReconcileInstrumentationPhase()); - } } public LoopPolicies createLoopPolicies() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java index 57c72bc63be..8ba0d99d1fd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java @@ -22,26 +22,26 @@ */ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; 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.ExpandLogicPhase; -import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.FixReadsPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; +import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase; import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase; -import org.graalvm.compiler.phases.common.instrumentation.InlineInstrumentationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.LowTierContext; public class LowTier extends PhaseSuite { @@ -50,41 +50,38 @@ public class LowTier extends PhaseSuite { // @formatter:off @Option(help = "", type = OptionType.Debug) - public static final OptionValue ProfileCompiledMethods = new OptionValue<>(false); + public static final OptionKey ProfileCompiledMethods = new OptionKey<>(false); // @formatter:on } - public LowTier() { + public LowTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + CanonicalizerPhase canonicalizerWithoutGVN = new CanonicalizerPhase(); + canonicalizerWithoutGVN.disableGVN(); + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); + canonicalizerWithoutGVN.disableReadCanonicalization(); } - if (Options.ProfileCompiledMethods.getValue()) { + if (Options.ProfileCompiledMethods.getValue(options)) { appendPhase(new ProfileCompiledMethodsPhase()); } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new InlineInstrumentationPhase()); - } - - appendPhase(new RemoveValueProxyPhase()); appendPhase(new ExpandLogicPhase()); - /* Cleanup IsNull checks resulting from MID_TIER/LOW_TIER lowering and ExpandLogic phase. */ - if (ConditionalElimination.getValue()) { - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); - /* Canonicalizer may create some new ShortCircuitOrNodes so clean them up. */ - appendPhase(new ExpandLogicPhase()); - } + appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS))); + + appendPhase(canonicalizerWithoutGVN); appendPhase(new UseTrappingNullChecksPhase()); appendPhase(new DeadCodeEliminationPhase(Required)); + appendPhase(new PropagateDeoptimizeProbabilityPhase()); + appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.FINAL_SCHEDULE)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java index dc79e143ae1..2c02e865a00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java @@ -25,17 +25,14 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.OptDeoptimizationGrouping; -import static org.graalvm.compiler.core.common.GraalOptions.OptEliminatePartiallyRedundantGuards; import static org.graalvm.compiler.core.common.GraalOptions.OptFloatingReads; -import static org.graalvm.compiler.core.common.GraalOptions.OptPushThroughPi; -import static org.graalvm.compiler.core.common.GraalOptions.OptReadElimination; import static org.graalvm.compiler.core.common.GraalOptions.ReassociateInvariants; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.core.common.GraalOptions.VerifyHeapAtReturn; import org.graalvm.compiler.loop.phases.LoopSafepointEliminationPhase; import org.graalvm.compiler.loop.phases.ReassociateInvariantPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeoptimizationGroupingPhase; @@ -47,79 +44,46 @@ import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LockEliminationPhase; import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.OptimizeGuardAnchorsPhase; -import org.graalvm.compiler.phases.common.PushThroughPiPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.common.VerifyHeapAtReturnPhase; -import org.graalvm.compiler.phases.common.instrumentation.MidTierReconcileInstrumentationPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; public class MidTier extends PhaseSuite { - public MidTier() { + public MidTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } - if (OptPushThroughPi.getValue()) { - appendPhase(new PushThroughPiPhase()); - } - - appendPhase(canonicalizer); - - appendPhase(new ValueAnchorCleanupPhase()); appendPhase(new LockEliminationPhase()); - if (OptReadElimination.getValue()) { - appendPhase(new EarlyReadEliminationPhase(canonicalizer)); - } - - if (OptFloatingReads.getValue()) { + if (OptFloatingReads.getValue(options)) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase())); } - appendPhase(new RemoveValueProxyPhase()); - appendPhase(canonicalizer); - - if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchorsPhase()); - } - - if (ConditionalElimination.getValue()) { + if (ConditionalElimination.getValue(options)) { appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, true)); } - if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchorsPhase()); - } - - appendPhase(canonicalizer); - - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopSafepointEliminationPhase())); + appendPhase(new LoopSafepointEliminationPhase()); appendPhase(new LoopSafepointInsertionPhase()); - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new GuardLoweringPhase())); + appendPhase(new GuardLoweringPhase()); - if (VerifyHeapAtReturn.getValue()) { + if (VerifyHeapAtReturn.getValue(options)) { appendPhase(new VerifyHeapAtReturnPhase()); } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new MidTierReconcileInstrumentationPhase()); - } appendPhase(new FrameStateAssignmentPhase()); - if (ReassociateInvariants.getValue()) { + if (ReassociateInvariants.getValue(options)) { appendPhase(new ReassociateInvariantPhase()); } - if (OptDeoptimizationGrouping.getValue()) { + if (OptDeoptimizationGrouping.getValue(options)) { appendPhase(new DeoptimizationGroupingPhase()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java index 53214afb9d3..68dc1187fde 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.core.target; -import java.util.Set; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -45,6 +43,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; @@ -61,18 +60,26 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.SpeculationLog; +import java.util.ArrayList; + /** * Represents a compiler backend for Graal. */ public abstract class Backend implements TargetProvider, ValueKindFactory { private final Providers providers; + private final ArrayList codeInstallationTaskFactories; public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class); public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class); protected Backend(Providers providers) { this.providers = providers; + this.codeInstallationTaskFactories = new ArrayList<>(); + } + + public synchronized void addCodeInstallationTask(CodeInstallationTaskFactory factory) { + this.codeInstallationTaskFactories.add(factory); } public Providers getProviders() { @@ -113,7 +120,13 @@ public abstract class Backend implements TargetProvider, ValueKindFactory translateToCallerRegisters(Set calleeRegisters); + public abstract EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters); /** * Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns @@ -231,4 +278,38 @@ public abstract class Backend implements TargetProvider, ValueKindFactory= spinA || timerB.getFlat().getCurrentValue() < timerA.getFlat().getCurrentValue()); - assertEquals(timerA.getFlat().getCurrentValue(), timerA.getCurrentValue() - timerB.getFlat().getCurrentValue(), 10D); - } - } - } - + /** + * Asserts that a timer replied recursively without any other interleaving timers has the same + * flat and accumulated times. + */ @Test public void test2() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); + OptionValues options = new OptionValues(EconomicMap.create()); + DebugConfig debugConfig = Debug.fixedConfig(options, 0, 0, false, false, true, false, false, null, null, System.out); try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { DebugTimer timerC = Debug.timer("TimerC"); try (DebugCloseable c1 = timerC.start()) { @@ -117,36 +95,4 @@ public class DebugTimerTest { } } } - - @Test - public void test3() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); - try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { - - DebugTimer timerD = Debug.timer("TimerD"); - DebugTimer timerE = Debug.timer("TimerE"); - - long spinD1; - long spinE; - - try (DebugCloseable d1 = timerD.start()) { - spinD1 = spin(50); - try (DebugCloseable e1 = timerE.start()) { - spinE = spin(50); - try (DebugCloseable d2 = timerD.start()) { - spin(50); - try (DebugCloseable d3 = timerD.start()) { - spin(50); - } - } - } - } - - Assert.assertTrue(timerE.getCurrentValue() < timerD.getCurrentValue()); - if (timerD.getFlat() != null && timerE.getFlat() != null) { - assertTrue(spinE >= spinD1 || timerE.getFlat().getCurrentValue() < timerD.getFlat().getCurrentValue()); - assertEquals(timerD.getFlat().getCurrentValue(), timerD.getCurrentValue() - timerE.getFlat().getCurrentValue(), 10D); - } - } - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java new file mode 100644 index 00000000000..ff12a8a64f8 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java @@ -0,0 +1,40 @@ +/* + * 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.debug; + +/** + * Utility for query whether assertions are enabled. + */ +public class Assertions { + /** + * Determines if assertions are enabled. Strictly speaking, this may only be true for the + * {@link Assertions} class but we assume assertions are enabled/disabled for Graal as a whole. + */ + public static final boolean ENABLED = assertionsEnabled(); + + private static boolean assertionsEnabled() { + boolean enabled = false; + assert (enabled = true) == true; + return enabled; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java index cd5e7fca7ae..86c442a29f6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.debug; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.LOG_METHOD; import static java.util.FormattableFlags.LEFT_JUSTIFY; import static java.util.FormattableFlags.UPPERCASE; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.LOG_METHOD; import java.io.PrintStream; import java.util.ArrayList; @@ -47,6 +47,8 @@ import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; import org.graalvm.compiler.debug.internal.TimerImpl; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionValuesAccess; import org.graalvm.compiler.serviceprovider.GraalServices; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -63,7 +65,12 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class Debug { - private static final Params params = new Params(); + /** + * The option values available in this package. + */ + static final OptionValues DEBUG_OPTIONS = GraalServices.loadSingle(OptionValuesAccess.class, true).getOptions(); + + static final Params params = new Params(); static { // Load the service providers that may want to modify any of the @@ -76,7 +83,7 @@ public class Debug { /** * The parameters for configuring the initialization of {@link Debug} class. */ - public static class Params { + public static final class Params { public boolean enable; public boolean enableMethodFilter; public boolean enableUnscopedTimers; @@ -86,13 +93,16 @@ public class Debug { public boolean interceptCount; public boolean interceptTime; public boolean interceptMem; + + @SuppressWarnings("static-method") + public OptionValues getOptions() { + return DEBUG_OPTIONS; + } } @SuppressWarnings("all") private static boolean initialize() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled || params.enable || GraalDebugConfig.Options.ForceDebugEnable.getValue(); + return Assertions.ENABLED || params.enable || GraalDebugConfig.Options.ForceDebugEnable.getValue(DEBUG_OPTIONS); } private static final boolean ENABLED = initialize(); @@ -112,11 +122,58 @@ public class Debug { return config.isDumpEnabledForMethod(); } - public static final int BASIC_LOG_LEVEL = 1; - public static final int INFO_LOG_LEVEL = 2; - public static final int VERBOSE_LOG_LEVEL = 3; - public static final int DETAILED_LOG_LEVEL = 4; - public static final int VERY_DETAILED_LOG_LEVEL = 5; + /** + * A special dump level that indicates the dumping machinery is enabled but no dumps will be + * produced except through other options. + */ + public static final int ENABLED_LEVEL = 0; + + /** + * Basic debug level. + * + * For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier, + * after mid tier, after low tier. + * + * LIR dumping: After LIR generation, after each pre-allocation, allocation and post allocation + * stage, and after code installation. + */ + public static final int BASIC_LEVEL = 1; + + /** + * Informational debug level. + * + * HIR dumping: One graph after each applied top-level phase. + * + * LIR dumping: After each applied phase. + */ + public static final int INFO_LEVEL = 2; + + /** + * Verbose debug level. + * + * HIR dumping: One graph after each phase (including sub phases). + * + * LIR dumping: After each phase including sub phases. + */ + public static final int VERBOSE_LEVEL = 3; + + /** + * Detailed debug level. + * + * HIR dumping: Graphs within phases where interesting for a phase, max ~5 per phase. + * + * LIR dumping: Dump CFG within phases where interesting. + */ + public static final int DETAILED_LEVEL = 4; + + /** + * Very detailed debug level. + * + * HIR dumping: Graphs per node granularity graph change (before/after change). + * + * LIR dumping: Intermediate CFGs of phases where interesting. + */ + public static final int VERY_DETAILED_LEVEL = 5; public static boolean isDumpEnabled(int dumpLevel) { return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel); @@ -173,7 +230,7 @@ public class Debug { } public static boolean isLogEnabled() { - return isLogEnabled(BASIC_LOG_LEVEL); + return isLogEnabled(BASIC_LEVEL); } public static boolean isLogEnabled(int logLevel) { @@ -410,7 +467,7 @@ public class Debug { } public static void log(String msg) { - log(BASIC_LOG_LEVEL, msg); + log(BASIC_LEVEL, msg); } /** @@ -425,7 +482,7 @@ public class Debug { } public static void log(String format, Object arg) { - log(BASIC_LOG_LEVEL, format, arg); + log(BASIC_LEVEL, format, arg); } /** @@ -441,7 +498,7 @@ public class Debug { } public static void log(String format, int arg) { - log(BASIC_LOG_LEVEL, format, arg); + log(BASIC_LEVEL, format, arg); } /** @@ -457,7 +514,7 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -470,7 +527,7 @@ public class Debug { } public static void log(String format, int arg1, Object arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -483,7 +540,7 @@ public class Debug { } public static void log(String format, Object arg1, int arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -496,7 +553,7 @@ public class Debug { } public static void log(String format, int arg1, int arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); + log(BASIC_LEVEL, format, arg1, arg2); } /** @@ -509,7 +566,7 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2, Object arg3) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + log(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -522,7 +579,7 @@ public class Debug { } public static void log(String format, int arg1, int arg2, int arg3) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + log(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -535,7 +592,7 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); } /** @@ -548,7 +605,7 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); } /** @@ -561,7 +618,7 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); } /** @@ -574,11 +631,11 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } /** @@ -597,7 +654,7 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { @@ -607,7 +664,7 @@ public class Debug { } public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { @@ -617,7 +674,7 @@ public class Debug { } public static void logv(String format, Object... args) { - logv(BASIC_LOG_LEVEL, format, args); + logv(BASIC_LEVEL, format, args); } /** @@ -645,7 +702,7 @@ public class Debug { @Deprecated public static void log(String format, Object[] args) { assert false : "shouldn't use this"; - log(BASIC_LOG_LEVEL, format, args); + log(BASIC_LEVEL, format, args); } /** @@ -660,6 +717,14 @@ public class Debug { logv(logLevel, format, args); } + /** + * Forces an unconditional dump. This method exists mainly for debugging. It can also be used to + * force a graph dump from IDEs that support invoking a Java method while at a breakpoint. + */ + public static void forceDump(Object object, String format, Object... args) { + DebugScope.forceDump(object, format, args); + } + public static void dump(int dumpLevel, Object object, String msg) { if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { DebugScope.getInstance().dump(dumpLevel, object, msg); @@ -705,7 +770,7 @@ public class Debug { * @param object object to verify * @param message description of verification context * - * @see DebugVerifyHandler#verify(Object, String) + * @see DebugVerifyHandler#verify(java.lang.Object, java.lang.String, java.lang.Object...) */ public static void verify(Object object, String message) { if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { @@ -721,7 +786,7 @@ public class Debug { * @param format a format string for the description of the verification context * @param arg the argument referenced by the format specifiers in {@code format} * - * @see DebugVerifyHandler#verify(Object, String) + * @see DebugVerifyHandler#verify(java.lang.Object, java.lang.String, java.lang.Object...) */ public static void verify(Object object, String format, Object arg) { if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { @@ -761,7 +826,7 @@ public class Debug { } public static Indent logAndIndent(String msg) { - return logAndIndent(BASIC_LOG_LEVEL, msg); + return logAndIndent(BASIC_LEVEL, msg); } /** @@ -779,7 +844,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg); + return logAndIndent(BASIC_LEVEL, format, arg); } /** @@ -798,7 +863,7 @@ public class Debug { } public static Indent logAndIndent(String format, int arg) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg); + return logAndIndent(BASIC_LEVEL, format, arg); } /** @@ -817,7 +882,7 @@ public class Debug { } public static Indent logAndIndent(String format, int arg1, Object arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -831,7 +896,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg1, int arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -845,7 +910,7 @@ public class Debug { } public static Indent logAndIndent(String format, int arg1, int arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -859,7 +924,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg1, Object arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); } /** @@ -873,7 +938,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -887,7 +952,7 @@ public class Debug { } public static Indent logAndIndent(String format, int arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -901,7 +966,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); } /** @@ -915,7 +980,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); } /** @@ -929,7 +994,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); } /** @@ -943,7 +1008,7 @@ public class Debug { } public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); } /** @@ -991,7 +1056,7 @@ public class Debug { @Deprecated public static void logAndIndent(String format, Object[] args) { assert false : "shouldn't use this"; - logAndIndent(BASIC_LOG_LEVEL, format, args); + logAndIndent(BASIC_LEVEL, format, args); } /** @@ -1239,14 +1304,21 @@ public class Debug { } public static DebugConfig silentConfig() { - return fixedConfig(0, 0, false, false, false, false, false, Collections. emptyList(), Collections. emptyList(), null); + return fixedConfig(new OptionValues(OptionValues.newOptionMap()), 0, 0, false, false, false, false, false, Collections. emptyList(), + Collections. emptyList(), null); } - public static DebugConfig fixedConfig(final int logLevel, final int dumpLevel, final boolean isCountEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled, + public static DebugConfig fixedConfig(OptionValues options, final int logLevel, final int dumpLevel, final boolean isCountEnabled, final boolean isMemUseTrackingEnabled, + final boolean isTimerEnabled, final boolean isVerifyEnabled, final boolean isMMEnabled, final Collection dumpHandlers, final Collection verifyHandlers, final PrintStream output) { return new DebugConfig() { + @Override + public OptionValues getOptions() { + return options; + } + @Override public int getLogLevel() { return logLevel; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java index 66b5c32311f..4bac721621e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java @@ -25,8 +25,15 @@ package org.graalvm.compiler.debug; import java.io.PrintStream; import java.util.Collection; +import org.graalvm.compiler.options.OptionValues; + public interface DebugConfig { + /** + * Returns the option values that can be used to configure details of debug clients. + */ + OptionValues getOptions(); + /** * Determines the current log level in the {@linkplain Debug#currentScope() current debug scope} * . diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java index 5b0f8518058..fcbebdbe8ac 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigCustomizer.java @@ -23,14 +23,5 @@ package org.graalvm.compiler.debug; public interface DebugConfigCustomizer { - void customize(DebugConfig config, Object... extraArgs); - - static T lookupArg(Class c, Object... extraArgs) { - for (Object arg : extraArgs) { - if (c.isInstance(arg)) { - return c.cast(arg); - } - } - return null; - } + void customize(DebugConfig config); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java index 3b52c31215b..5534051b1f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java @@ -26,12 +26,20 @@ import java.io.Closeable; public interface DebugDumpHandler extends Closeable { - void dump(Object object, String message); + void dump(Object object, String format, Object... arguments); + + /** + * Add arbitrary capability for use by the handler. + * + * @param capability + */ + default void addCapability(Object capability) { + } /** * Flushes and releases resources managed by this dump handler. A subsequent call to - * {@link #dump(Object, String)} will create and open new resources. That is, this method can be - * used to reset the handler. + * {@link #dump(java.lang.Object, java.lang.String, java.lang.Object...)} will create and open + * new resources. That is, this method can be used to reset the handler. */ @Override void close(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java index 9a15e241822..c16336d77cd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java @@ -22,43 +22,84 @@ */ package org.graalvm.compiler.debug; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Count; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Count; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodMeter; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Time; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.TrackMemUse; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodMeter; -import java.io.PrintStream; import java.util.ArrayList; import java.util.List; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.serviceprovider.GraalServices; import jdk.vm.ci.runtime.JVMCI; public class DebugEnvironment { - public static GraalDebugConfig initialize(PrintStream log, Object... extraArgs) { - // Initialize JVMCI before loading class Debug - JVMCI.initialize(); + /** + * Create a GraalDebugConfig if {@link Debug#isEnabled()} is true and one hasn't already been + * created. Additionally add {@code extraArgs} as capabilities to the {@link DebugDumpHandler}s + * associated with the current config. Capabilities can be added at any time. + * + * @return the current {@link GraalDebugConfig} or null if nothing was done + */ + public static GraalDebugConfig ensureInitialized(OptionValues options, Object... capabilities) { + return ensureInitializedHelper(options, false, capabilities); + } + + /** + * Create a new GraalDebugConfig if {@link Debug#isEnabled()} is true, even if one had already + * been created. Additionally add {@code extraArgs} as capabilities to the + * {@link DebugDumpHandler}s associated with the current config. Capabilities can be added at + * any time. + * + * @return the current {@link GraalDebugConfig} or null if nothing was done + */ + public static GraalDebugConfig forceInitialization(OptionValues options, Object... capabilities) { + return ensureInitializedHelper(options, true, capabilities); + } + + private static GraalDebugConfig ensureInitializedHelper(OptionValues options, boolean forceInit, Object... capabilities) { if (!Debug.isEnabled()) { - log.println("WARNING: Scope debugging needs to be enabled with -esa"); return null; } - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Count.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), Verify.getValue(), MethodFilter.getValue(), - MethodMeter.getValue(), - log, dumpHandlers, verifyHandlers); + GraalDebugConfig debugConfig = (GraalDebugConfig) DebugScope.getConfig(); + if (debugConfig == null || forceInit || options != debugConfig.getOptions()) { + // Initialize JVMCI before loading class Debug + JVMCI.initialize(); + List dumpHandlers = new ArrayList<>(); + List verifyHandlers = new ArrayList<>(); + debugConfig = new GraalDebugConfig( + options, + Log.getValue(options), + Count.getValue(options), + TrackMemUse.getValue(options), + Time.getValue(options), + Dump.getValue(options), + Verify.getValue(options), + MethodFilter.getValue(options), + MethodMeter.getValue(options), + TTY.out, dumpHandlers, verifyHandlers); - for (DebugConfigCustomizer customizer : GraalServices.load(DebugConfigCustomizer.class)) { - customizer.customize(debugConfig, extraArgs); + for (DebugConfigCustomizer customizer : GraalServices.load(DebugConfigCustomizer.class)) { + customizer.customize(debugConfig); + } + + Debug.setConfig(debugConfig); + } + if (capabilities != null) { + for (Object o : capabilities) { + for (DebugDumpHandler handler : debugConfig.dumpHandlers()) { + handler.addCapability(o); + } + } } - - Debug.setConfig(debugConfig); return debugConfig; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java index 0345a548a09..79871325567 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java @@ -41,28 +41,28 @@ import org.graalvm.compiler.debug.internal.DebugScope; * A filter is a list of comma-separated terms of the form {@code [:]}. {@code * } is interpreted as a glob pattern if it contains a "*" or "?" character. Otherwise, it * is interpreted as a substring. If {@code } is empty, it matches every scope. If {@code : - * } is omitted, it defaults to {@link Debug#BASIC_LOG_LEVEL}. The term {@code ~} is - * a shorthand for {@code :0} to disable a debug facility for a pattern. + * } is omitted, it defaults to {@link Debug#BASIC_LEVEL}. The term {@code ~} is a + * shorthand for {@code :0} to disable a debug facility for a pattern. *

    * The resulting log level of a scope is determined by the last matching term. If no term * matches, the log level is 0 (disabled). A filter with no terms matches every scope with a log - * level of {@link Debug#BASIC_LOG_LEVEL}. + * level of {@link Debug#BASIC_LEVEL}. * *

    Examples of filters

    * *
      *
    • (empty string)
      - * Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches any scope with log level {@link Debug#BASIC_LEVEL}. * *
    • {@code :1}
      * Matches any scope with log level 1. * *
    • {@code *}
      - * Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches any scope with log level {@link Debug#BASIC_LEVEL}. * *
    • {@code CodeGen,CodeInstall}
      * Matches scopes containing "CodeGen" or "CodeInstall", both with log level - * {@link Debug#BASIC_LOG_LEVEL}. + * {@link Debug#BASIC_LEVEL}. * *
    • {@code CodeGen:2,CodeInstall:1}
      * Matches scopes containing "CodeGen" with log level 2, or "CodeInstall" with log level 1. @@ -74,10 +74,10 @@ import org.graalvm.compiler.debug.internal.DebugScope; * Matches all scopes with log level 1, except those containing "Dead". * *
    • {@code Code*}
      - * Matches scopes starting with "Code" with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches scopes starting with "Code" with log level {@link Debug#BASIC_LEVEL}. * *
    • {@code Code,~Dead}
      - * Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LEVEL}. *
    */ final class DebugFilter { @@ -108,7 +108,7 @@ final class DebugFilter { level = 0; } else { pattern = t; - level = Debug.BASIC_LOG_LEVEL; + level = Debug.BASIC_LEVEL; } } else { pattern = t.substring(0, idx); @@ -119,13 +119,13 @@ final class DebugFilter { } catch (NumberFormatException e) { switch (levelString) { case "basic": - level = Debug.BASIC_LOG_LEVEL; + level = Debug.BASIC_LEVEL; break; case "info": - level = Debug.INFO_LOG_LEVEL; + level = Debug.INFO_LEVEL; break; case "verbose": - level = Debug.VERBOSE_LOG_LEVEL; + level = Debug.VERBOSE_LEVEL; break; default: throw new IllegalArgumentException("Unknown dump level: \"" + levelString + "\" expected basic, info, verbose or an integer"); @@ -133,7 +133,7 @@ final class DebugFilter { } } else { - level = Debug.BASIC_LOG_LEVEL; + level = Debug.BASIC_LEVEL; } } @@ -147,7 +147,7 @@ final class DebugFilter { */ public int matchLevel(String input) { if (terms == null) { - return Debug.BASIC_LOG_LEVEL; + return Debug.BASIC_LEVEL; } else { int level = 0; for (Term t : terms) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java new file mode 100644 index 00000000000..faab5373433 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java @@ -0,0 +1,72 @@ +/* + * 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.debug; + +import org.graalvm.compiler.debug.Debug.Scope; + +/** + * A mechanism for re-executing a task upon failure. + */ +public abstract class DebugRetryableTask extends DelegatingDebugConfig { + + /** + * Calls {@link #run} on this task and if it results in an exception, calls + * {@link #onRetry(Throwable)} and if that returns {@code true}, calls {@link #run}. + */ + @SuppressWarnings("try") + public final T execute() { + try { + return run(null); + } catch (Throwable t) { + if (onRetry(t)) { + try (Scope d = Debug.sandbox("Retrying: " + this, this)) { + return run(t); + } catch (Throwable t2) { + throw Debug.handle(t2); + } + } else { + throw t; + } + } + } + + /** + * Runs this task. + * + * @param failure the cause of the first execution to fail or {@code null} if this is the first + * execution of {@link #run(Throwable)} + */ + protected abstract T run(Throwable failure); + + /** + * Notifies this object that the initial execution failed with exception {@code t} and is about + * to be re-executed. The re-execution will use this object as the active {@link DebugConfig}. + * As such, this method can be overridden to enable more detailed debug facilities. + * + * @param t an exception that terminated the first execution of this task + * @return whether this task should be re-executed. If false, {@code t} will be re-thrown. + */ + protected boolean onRetry(Throwable t) { + return true; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java index d949f97bd06..c427336a352 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java @@ -31,7 +31,8 @@ public interface DebugVerifyHandler { * Verifies that a given object satisfies some invariants. * * @param object object to verify - * @param message description of verification context + * @param format description of verification context + * @param args arguments for the format */ - void verify(Object object, String message); + void verify(Object object, String format, Object... args); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java index ac336ae9ba7..4c08b6d2ff1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java @@ -28,6 +28,7 @@ import java.util.EnumMap; import java.util.Map; import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.options.OptionValues; public class DelegatingDebugConfig implements DebugConfig { @@ -131,6 +132,11 @@ public class DelegatingDebugConfig implements DebugConfig { return this; } + @Override + public OptionValues getOptions() { + return delegate.getOptions(); + } + @Override public int getLogLevel() { Integer ls = levelState.get(Level.LOG); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java deleted file mode 100644 index 367d0ddfb04..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; - -/** - * Facility for fingerprinting execution. - */ -public class Fingerprint implements AutoCloseable { - - public static class Options { - @Option(help = "Enables execution fingerprinting.")// - public static final OptionValue UseFingerprinting = new OptionValue<>(false); - - @Option(help = "Limit number of events shown in fingerprinting error message.")// - public static final OptionValue FingerprintErrorEventTailLength = new OptionValue<>(50); - - @Option(help = "Fingerprinting event at which to execute breakpointable code.")// - public static final OptionValue FingerprintingBreakpointEvent = new OptionValue<>(-1); - } - - /** - * Determines whether fingerprinting is enabled. - */ - public static final boolean ENABLED = Options.UseFingerprinting.getValue(); - - private static final ThreadLocal current = ENABLED ? new ThreadLocal<>() : null; - - private final List events; - private int index; - - /** - * Creates an object to record a fingerprint. - */ - public Fingerprint() { - events = new ArrayList<>(); - index = -1; - } - - /** - * Creates an object to verify execution matches a given fingerprint. - * - * @param toVerifyAgainst the fingerprint events to verify against - */ - public Fingerprint(List toVerifyAgainst) { - this.events = toVerifyAgainst; - index = 0; - } - - /** - * Creates an object to verify execution matches a given fingerprint. - * - * @param toVerifyAgainst the fingerprint to verify against - */ - public Fingerprint(Fingerprint toVerifyAgainst) { - this(toVerifyAgainst.events); - } - - public Collection getEvents() { - return Collections.unmodifiableCollection(events); - } - - /** - * Starts fingerprint recording or verification for the current thread. At most one fingerprint - * object can be active for any thread. - */ - public Fingerprint open() { - if (ENABLED) { - assert current.get() == null; - current.set(this); - return this; - } - return null; - } - - /** - * Finishes fingerprint recording or verification for the current thread. - */ - @Override - public void close() { - if (ENABLED) { - assert current.get() == this; - current.set(null); - } - } - - private static final int BREAKPOINT_EVENT = Options.FingerprintingBreakpointEvent.getValue(); - - /** - * Submits an execution event for the purpose of recording or verifying a fingerprint. This must - * only be called if {@link #ENABLED} is {@code true}. - */ - public static void submit(String format, Object... args) { - assert ENABLED : "fingerprinting must be enabled (-Dgraal." + Options.UseFingerprinting.getName() + "=true)"; - Fingerprint fingerprint = current.get(); - if (fingerprint != null) { - int eventId = fingerprint.nextEventId(); - if (eventId == BREAKPOINT_EVENT) { - // Set IDE breakpoint on the following line and set the relevant - // system property to debug a fingerprint verification error. - System.console(); - } - fingerprint.event(String.format(eventId + ": " + format, args)); - } - } - - private int nextEventId() { - return index == -1 ? events.size() : index; - } - - private static final int MAX_EVENT_TAIL_IN_ERROR_MESSAGE = Options.FingerprintErrorEventTailLength.getValue(); - - private String tail() { - int start = Math.max(index - MAX_EVENT_TAIL_IN_ERROR_MESSAGE, 0); - return events.subList(start, index).stream().collect(Collectors.joining(String.format("%n"))); - } - - private void event(String entry) { - if (index == -1) { - events.add(entry); - } else { - if (index > events.size()) { - throw new InternalError(String.format("%s%nOriginal fingerprint limit reached", tail())); - } - String l = events.get(index); - if (!l.equals(entry)) { - throw new InternalError(String.format("%s%nFingerprint differs at event %d%nexpected: %s%n actual: %s", tail(), index, l, entry)); - } - index++; - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java index 69c6e466aab..8373ee1e62c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java @@ -32,119 +32,119 @@ import java.util.Map; import java.util.Set; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.JavaMethod; public class GraalDebugConfig implements DebugConfig { - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } public static class Options { // @formatter:off @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) - public static final OptionValue Dump = new OptionValue<>(null); + public static final OptionKey Dump = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which counting is enabled (see DebugFilter and Debug.counter). " + "An empty value enables all counters unconditionally.", type = OptionType.Debug) - public static final OptionValue Count = new OptionValue<>(null); + public static final OptionKey Count = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) - public static final OptionValue Verify = new OptionValue() { - @Override - protected String defaultValue() { - return assertionsEnabled() ? "" : null; - } - }; + public static final OptionKey Verify = new OptionKey<>(Assertions.ENABLED ? "" : null); @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.counter). " + "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) - public static final OptionValue TrackMemUse = new OptionValue<>(null); + public static final OptionKey TrackMemUse = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer). " + "An empty value enables all timers unconditionally.", type = OptionType.Debug) - public static final OptionValue Time = new OptionValue<>(null); + public static final OptionKey Time = new OptionKey<>(null); @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) - public static final OptionValue Log = new OptionValue<>(null); + public static final OptionKey Log = new OptionKey<>(null); @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) - public static final OptionValue MethodFilter = new OptionValue<>(null); + public static final OptionKey MethodFilter = new OptionKey<>(null); @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) - public static final OptionValue MethodFilterRootOnly = new OptionValue<>(false); + public static final OptionKey MethodFilterRootOnly = new OptionKey<>(false); + @Option(help = "Dump a before and after graph if the named phase changes the graph.%n" + + "The argument is substring matched against the simple name of the phase class", type = OptionType.Debug) + public static final OptionKey DumpOnPhaseChange = new OptionKey<>(null); @Option(help = "How to print counters and timing values:%n" + "Name - aggregate by unqualified name%n" + "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" + "Complete - aggregate by qualified name%n" + "Thread - aggregate by qualified name and thread", type = OptionType.Debug) - public static final OptionValue DebugValueSummary = new OptionValue<>("Name"); + public static final OptionKey DebugValueSummary = new OptionKey<>("Name"); @Option(help = "Print counters and timers in a human readable form.", type = OptionType.Debug) - public static final OptionValue DebugValueHumanReadable = new OptionValue<>(true); + public static final OptionKey DebugValueHumanReadable = new OptionKey<>(true); @Option(help = "Omit reporting 0-value counters", type = OptionType.Debug) - public static final OptionValue SuppressZeroDebugValues = new OptionValue<>(true); + public static final OptionKey SuppressZeroDebugValues = new OptionKey<>(true); @Option(help = "Only report debug values for maps which match the regular expression.", type = OptionType.Debug) - public static final OptionValue DebugValueThreadFilter = new OptionValue<>(null); + public static final OptionKey DebugValueThreadFilter = new OptionKey<>(null); @Option(help = "Write debug values into a file instead of the terminal. " + "If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug) - public static final OptionValue DebugValueFile = new OptionValue<>(null); - @Option(help = "Send Graal compiler IR to dump handlers on error", type = OptionType.Debug) - public static final OptionValue DumpOnError = new OptionValue<>(false); + public static final OptionKey DebugValueFile = new OptionKey<>(null); + @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug) + public static final OptionKey DebugStubsAndSnippets = new OptionKey<>(false); + @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug) + public static final OptionKey DumpOnError = new OptionKey<>(false); @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) - public static final OptionValue InterceptBailout = new OptionValue<>(false); + public static final OptionKey InterceptBailout = new OptionKey<>(false); @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) - public static final OptionValue LogVerbose = new OptionValue<>(false); + public static final OptionKey LogVerbose = new OptionKey<>(false); @Option(help = "The directory where various Graal dump files are written.") - public static final OptionValue DumpPath = new OptionValue<>("."); + public static final OptionKey DumpPath = new OptionKey<>("."); @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug) - public static final OptionValue PrintCFG = new OptionValue<>(false); + public static final OptionKey PrintCFG = new OptionKey<>(false); @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) - public static final OptionValue PrintBackendCFG = new OptionValue<>(true); + public static final OptionKey PrintBackendCFG = new OptionKey<>(true); @Option(help = "Base filename when dumping C1Visualizer output to files.", type = OptionType.Debug) - public static final OptionValue PrintCFGFileName = new OptionValue<>("compilations"); + public static final OptionKey PrintCFGFileName = new OptionKey<>("compilations"); - @Option(help = "Output probabilities for fixed nodes during binary graph dumping", type = OptionType.Debug) - public static final OptionValue PrintGraphProbabilities = new OptionValue<>(false); + @Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug) + public static final OptionKey PrintGraphProbabilities = new OptionKey<>(false); @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraph = new OptionValue<>(true); - @Option(help = "Dump IdealGraphVisualizer output in binary format", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphs = new OptionValue<>(true); - @Option(help = "Print Ideal graphs as opposed to sending them over the network.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFile = new OptionValue<>(false); - @Option(help = "Base filename when dumping Ideal graphs to files.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFileName = new OptionValue<>("runtime-graphs"); + public static final OptionKey PrintGraph = new OptionKey<>(true); + @Option(help = "Dump graphs in binary format instead of XML format.", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphs = new OptionKey<>(true); + @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug) + public static final OptionKey PrintGraphFile = new OptionKey<>(false); + @Option(help = "Base filename when dumping graphs to files.", type = OptionType.Debug) + public static final OptionKey PrintGraphFileName = new OptionKey<>("runtime-graphs"); + + @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) + public static final OptionKey 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 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) + public static final OptionKey PrintBinaryGraphPort = new OptionKey<>(4445); + @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphWithSchedule = new OptionKey<>(false); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphPort = new OptionValue<>(4444); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphPort = new OptionValue<>(4445); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphSchedule = new OptionValue<>(false); @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintTruffleTrees = new OptionValue<>(true); + public static final OptionKey PrintTruffleTrees = new OptionKey<>(true); + + @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug) + public static final OptionKey DumpingErrorsAreFatal = new OptionKey<>(false); @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStrings = new OptionValue<>(false); + public static final OptionKey PrintCanonicalGraphStrings = new OptionKey<>(false); @Option(help = "Base directory when dumping graphs strings to files.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringsDirectory = new OptionValue<>("graph-strings"); + public static final OptionKey PrintCanonicalGraphStringsDirectory = new OptionKey<>("graph-strings"); @Option(help = "Choose format used when dumping canonical text for graphs: " + "0 gives a scheduled graph (better for spotting changes involving the schedule)" + "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringFlavor = new OptionValue<>(0); + public static final OptionKey PrintCanonicalGraphStringFlavor = new OptionKey<>(0); @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsExcludeVirtuals = new OptionValue<>(true); + public static final OptionKey CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true); @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsCheckConstants = new OptionValue<>(false); + public static final OptionKey CanonicalGraphStringsCheckConstants = new OptionKey<>(false); @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsRemoveIdentities = new OptionValue<>(true); + public static final OptionKey CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true); @Option(help = "Enable per method metrics that are collected across all compilations of a method." + "Pattern for scope(s) in which method metering is enabled (see DebugFilter and Debug.metric).", type = OptionType.Debug) - public static final OptionValue MethodMeter = new OptionValue<>(null); + public static final OptionKey MethodMeter = new OptionKey<>(null); @Option(help = "If a global metric (DebugTimer, DebugCounter or DebugMemUseTracker) is enabled in the same scope as a method metric, " + "use the global metric to update the method metric for the current compilation. " + "This option enables the re-use of global metrics on per-compilation basis. " + @@ -152,36 +152,70 @@ public class GraalDebugConfig implements DebugConfig { "as the global metric. " + "This option incurs a small but constant overhead due to the context method lookup at each metric update. " + "Format to specify GlobalMetric interception:(Timers|Counters|MemUseTrackers)(,Timers|,Counters|,MemUseTrackers)*", type = OptionType.Debug) - public static final OptionValue GlobalMetricsInterceptedByMethodMetrics = new OptionValue<>(null); + public static final OptionKey GlobalMetricsInterceptedByMethodMetrics = new OptionKey<>(null); @Option(help = "Force-enable debug code paths", type = OptionType.Debug) - public static final OptionValue ForceDebugEnable = new OptionValue<>(false); + public static final OptionKey ForceDebugEnable = new OptionKey<>(false); @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) - public static final OptionValue ClearMetricsAfterBootstrap = new OptionValue<>(false); + public static final OptionKey ClearMetricsAfterBootstrap = new OptionKey<>(false); @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug) - public static final OptionValue BootstrapInitializeOnly = new OptionValue<>(false); + public static final OptionKey BootstrapInitializeOnly = new OptionKey<>(false); + + // These + @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphAddress = new DeprecatedOptionKey<>(PrintGraphHost); + @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphSchedule = new DeprecatedOptionKey<>(PrintGraphWithSchedule); + @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraph = new DeprecatedOptionKey<>(PrintGraph); + @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFile = new DeprecatedOptionKey<>(PrintGraphFile); + @Option(help = "Deprecated - use PrintGraphFileName instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFileName = new DeprecatedOptionKey<>(PrintGraphFileName); + @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphPort = new DeprecatedOptionKey<>(PrintXmlGraphPort); // @formatter:on } - public static boolean isNotEmpty(OptionValue option) { - return option.getValue() != null && !option.getValue().isEmpty(); + static class DeprecatedOptionKey extends OptionKey { + private final OptionKey replacement; + + DeprecatedOptionKey(OptionKey replacement) { + super(replacement.getDefaultValue()); + this.replacement = replacement; + } + + @Override + protected void onValueUpdate(EconomicMap, Object> values, T oldValue, T newValue) { + // Ideally we'd use TTY here but it may not yet be initialized. + System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName()); + replacement.update(values, newValue); + } } - public static boolean areDebugScopePatternsEnabled() { - return Options.DumpOnError.getValue() || Options.Dump.getValue() != null || Options.Log.getValue() != null || areScopedGlobalMetricsEnabled(); + public static boolean isNotEmpty(OptionKey option, OptionValues options) { + return option.getValue(options) != null && !option.getValue(options).isEmpty(); } - public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled() { - return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics); + public static boolean areDebugScopePatternsEnabled(OptionValues options) { + return Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null || Options.Log.getValue(options) != null || areScopedGlobalMetricsEnabled(options); + } + + public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled(OptionValues options) { + return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics, options); } /** * Determines if any of {@link Options#Count}, {@link Options#Time} or * {@link Options#TrackMemUse} has a non-null, non-empty value. + * + * @param options */ - public static boolean areScopedGlobalMetricsEnabled() { - return isNotEmpty(Options.Count) || isNotEmpty(Options.Time) || isNotEmpty(Options.TrackMemUse) || isNotEmpty(Options.MethodMeter); + public static boolean areScopedGlobalMetricsEnabled(OptionValues options) { + return isNotEmpty(Options.Count, options) || isNotEmpty(Options.Time, options) || isNotEmpty(Options.TrackMemUse, options) || isNotEmpty(Options.MethodMeter, options); } + private final OptionValues options; + private final DebugFilter countFilter; private final DebugFilter logFilter; private final DebugFilter methodMetricsFilter; @@ -197,8 +231,9 @@ public class GraalDebugConfig implements DebugConfig { // Use an identity set to handle context objects that don't support hashCode(). private final Set extraFilters = Collections.newSetFromMap(new IdentityHashMap<>()); - public GraalDebugConfig(String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, + public GraalDebugConfig(OptionValues options, String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, String methodMetricsFilter, PrintStream output, List dumpHandlers, List verifyHandlers) { + this.options = options; this.logFilter = DebugFilter.parse(logFilter); this.countFilter = DebugFilter.parse(countFilter); this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); @@ -212,15 +247,16 @@ public class GraalDebugConfig implements DebugConfig { this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); } - // Report the filters that have been configured so the user can verify it's what they expect - if (logFilter != null || countFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { - // TTY.println(Thread.currentThread().getName() + ": " + toString()); - } this.dumpHandlers = dumpHandlers; this.verifyHandlers = verifyHandlers; this.output = output; } + @Override + public OptionValues getOptions() { + return options; + } + @Override public int getLogLevel() { return getLevel(logFilter); @@ -287,8 +323,8 @@ public class GraalDebugConfig implements DebugConfig { } else { level = filter.matchLevel(Debug.currentScope()); } - if (level > 0 && !checkMethodFilter()) { - level = 0; + if (level >= 0 && !checkMethodFilter()) { + level = -1; } return level; } @@ -323,7 +359,7 @@ public class GraalDebugConfig implements DebugConfig { } else if (methodFilter != null) { JavaMethod method = asJavaMethod(o); if (method != null) { - if (!Options.MethodFilterRootOnly.getValue()) { + if (!Options.MethodFilterRootOnly.getValue(options)) { if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { return true; } @@ -373,18 +409,18 @@ public class GraalDebugConfig implements DebugConfig { @Override public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException && !Options.InterceptBailout.getValue()) { + if (e instanceof BailoutException && !Options.InterceptBailout.getValue(options)) { return null; } - Debug.setConfig(Debug.fixedConfig(Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); + Debug.setConfig(Debug.fixedConfig(options, Debug.BASIC_LEVEL, Debug.BASIC_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); Debug.log("Exception occurred in scope: %s", Debug.currentScope()); Map firstSeen = new IdentityHashMap<>(); for (Object o : Debug.context()) { // Only dump a context object once. if (!firstSeen.containsKey(o)) { firstSeen.put(o, o); - if (Options.DumpOnError.getValue()) { - Debug.dump(Debug.BASIC_LOG_LEVEL, o, "Exception: %s", e); + if (Options.DumpOnError.getValue(options) || Options.Dump.getValue(options) != null) { + Debug.dump(Debug.BASIC_LEVEL, o, "Exception: %s", e); } else { Debug.log("Context obj %s", o); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java index 4ff6cc51ffa..cc0737e2180 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java @@ -53,6 +53,21 @@ public class GraalError extends Error { throw new GraalError(cause); } + /** + * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are + * stronger than assertions in that they are always checked. Error messages for guarantee + * violations should clearly indicate the nature of the problem as well as a suggested solution + * if possible. + * + * @param condition the condition to check + * @param msg the message that will be associated with the error + */ + public static void guarantee(boolean condition, String msg) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg); + } + } + /** * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are * stronger than assertions in that they are always checked. Error messages for guarantee @@ -62,8 +77,58 @@ public class GraalError extends Error { * @param condition the condition to check * @param msg the message that will be associated with the error, in * {@link String#format(String, Object...)} syntax - * @param args arguments to the format string + * @param arg argument to the format string in {@code msg} */ + public static void guarantee(boolean condition, String msg, Object arg) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg, arg); + } + } + + /** + * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are + * stronger than assertions in that they are always checked. Error messages for guarantee + * violations should clearly indicate the nature of the problem as well as a suggested solution + * if possible. + * + * @param condition the condition to check + * @param msg the message that will be associated with the error, in + * {@link String#format(String, Object...)} syntax + * @param arg1 argument to the format string in {@code msg} + * @param arg2 argument to the format string in {@code msg} + */ + public static void guarantee(boolean condition, String msg, Object arg1, Object arg2) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg, arg1, arg2); + } + } + + /** + * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are + * stronger than assertions in that they are always checked. Error messages for guarantee + * violations should clearly indicate the nature of the problem as well as a suggested solution + * if possible. + * + * @param condition the condition to check + * @param msg the message that will be associated with the error, in + * {@link String#format(String, Object...)} syntax + * @param arg1 argument to the format string in {@code msg} + * @param arg2 argument to the format string in {@code msg} + * @param arg3 argument to the format string in {@code msg} + */ + public static void guarantee(boolean condition, String msg, Object arg1, Object arg2, Object arg3) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg, arg1, arg2, arg3); + } + } + + /** + * This override exists to catch cases when {@link #guarantee(boolean, String, Object)} is + * called with one argument bound to a varargs method parameter. It will bind to this method + * instead of the single arg variant and produce a deprecation warning instead of silently + * wrapping the Object[] inside of another Object[]. + */ + @Deprecated public static void guarantee(boolean condition, String msg, Object... args) { if (!condition) { throw new GraalError("failed guarantee: " + msg, args); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java index f7bc3d7bd74..87caf09f237 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java @@ -42,7 +42,7 @@ public class TTY { /** * Support for thread-local suppression of {@link TTY}. */ - public static class Filter { + public static class Filter implements AutoCloseable { private LogStream previous; private final Thread thread = Thread.currentThread(); @@ -87,6 +87,16 @@ public class TTY { log.set(LogStream.SINK); } + /** + * Creates an object that will overwrite {@link TTY} for the current thread with a custom + * log stream. To revert the overwritten state to how it was before this call, the + * {@link #remove()} method must be called on this filter object. + */ + public Filter(LogStream newStream) { + previous = out(); + log.set(newStream); + } + /** * Reverts the suppression state of {@link TTY} to how it was before this object was * constructed. @@ -97,6 +107,11 @@ public class TTY { log.set(previous); } } + + @Override + public void close() { + remove(); + } } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java index 35261253c3c..2fc4865f658 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java @@ -235,7 +235,7 @@ public final class DebugScope implements Debug.Scope { } public boolean isDumpEnabled(int dumpLevel) { - assert dumpLevel > 0; + assert dumpLevel >= 0; return currentDumpLevel >= dumpLevel; } @@ -333,9 +333,8 @@ public final class DebugScope implements Debug.Scope { if (isDumpEnabled(dumpLevel)) { DebugConfig config = getConfig(); if (config != null) { - String message = String.format(formatString, args); for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { - dumpHandler.dump(object, message); + dumpHandler.dump(object, formatString, args); } } } @@ -347,12 +346,11 @@ public final class DebugScope implements Debug.Scope { public static void forceDump(Object object, String format, Object... args) { DebugConfig config = getConfig(); if (config != null) { - String message = String.format(format, args); for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { - dumpHandler.dump(object, message); + dumpHandler.dump(object, format, args); } } else { - TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.Dump=xxx"); + TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.ForceDebugEnable=true"); } } @@ -363,9 +361,8 @@ public final class DebugScope implements Debug.Scope { if (isVerifyEnabled()) { DebugConfig config = getConfig(); if (config != null) { - String message = String.format(formatString, args); for (DebugVerifyHandler handler : config.verifyHandlers()) { - handler.verify(object, message); + handler.verify(object, formatString, args); } } } @@ -403,21 +400,27 @@ public final class DebugScope implements Debug.Scope { public RuntimeException handle(Throwable e) { DebugScope lastClosed = lastClosedTL.get(); - assert lastClosed.parent == this : "Debug.handle() used with no matching Debug.scope(...) or Debug.sandbox(...)"; - if (e != lastExceptionThrownTL.get()) { - RuntimeException newException = null; - instanceTL.set(lastClosed); - try (DebugScope s = lastClosed) { - newException = s.interceptException(e); - } - assert instanceTL.get() == this; - assert lastClosed == lastClosedTL.get(); - if (newException == null) { - lastExceptionThrownTL.set(e); - } else { - lastExceptionThrownTL.set(newException); - throw newException; + try { + assert lastClosed.parent == this : "Debug.handle() used with no matching Debug.scope(...) or Debug.sandbox(...) " + + "or an exception occurred while opening a scope"; + if (e != lastExceptionThrownTL.get()) { + RuntimeException newException = null; + instanceTL.set(lastClosed); + try (DebugScope s = lastClosed) { + newException = s.interceptException(e); + } + assert instanceTL.get() == this; + assert lastClosed == lastClosedTL.get(); + if (newException == null) { + lastExceptionThrownTL.set(e); + } else { + lastExceptionThrownTL.set(newException); + throw newException; + } } + } catch (Throwable t) { + t.initCause(e); + throw t; } if (e instanceof Error) { throw (Error) e; @@ -435,7 +438,7 @@ public final class DebugScope implements Debug.Scope { memUseTrackingEnabled = false; timeEnabled = false; verifyEnabled = false; - currentDumpLevel = 0; + currentDumpLevel = -1; methodMetricsEnabled = false; // Be pragmatic: provide a default log stream to prevent a crash if the stream is not // set while logging diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java index 90af22bf09d..bd3812ce2f7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java @@ -35,7 +35,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Pattern; -import java.util.stream.Collectors; import org.graalvm.compiler.debug.CSVUtil; import org.graalvm.compiler.debug.GraalError; @@ -43,6 +42,8 @@ import org.graalvm.compiler.debug.LogStream; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.CollectionsUtil; /** * Facility for printing the {@linkplain KeyRegistry#getDebugValues() values} collected across all @@ -61,7 +62,7 @@ public class DebugValuesPrinter { this.mmPrinter = mmPrinter; } - public void printDebugValues() throws GraalError { + public void printDebugValues(OptionValues options) throws GraalError { TTY.println(); TTY.println(""); List topLevelMaps = DebugValueMap.getTopLevelMaps(); @@ -71,20 +72,20 @@ public class DebugValuesPrinter { ArrayList sortedValues = new ArrayList<>(debugValues); Collections.sort(sortedValues); - String summary = DebugValueSummary.getValue(); + String summary = DebugValueSummary.getValue(options); if (summary == null) { summary = "Complete"; } - if (DebugValueThreadFilter.getValue() != null && topLevelMaps.size() != 0) { - topLevelMaps = topLevelMaps.stream().filter(map -> Pattern.compile(DebugValueThreadFilter.getValue()).matcher(map.getName()).find()).collect(Collectors.toList()); + if (DebugValueThreadFilter.getValue(options) != null && topLevelMaps.size() != 0) { + topLevelMaps = CollectionsUtil.filterToList(topLevelMaps, map -> Pattern.compile(DebugValueThreadFilter.getValue(options)).matcher(map.getName()).find()); if (topLevelMaps.size() == 0) { - TTY.println("Warning: DebugValueThreadFilter=%s eliminated all maps so nothing will be printed", DebugValueThreadFilter.getValue()); + TTY.println("Warning: DebugValueThreadFilter=%s eliminated all maps so nothing will be printed", DebugValueThreadFilter.getValue(options)); } } switch (summary) { case "Name": { - LogStream log = getLogStream(); - printSummary(log, topLevelMaps, sortedValues); + LogStream log = getLogStream(options); + printSummary(options, log, topLevelMaps, sortedValues); break; } case "Partial": { @@ -93,8 +94,8 @@ public class DebugValuesPrinter { flattenChildren(map, globalMap); } globalMap.normalize(); - LogStream log = getLogStream(); - printMap(log, new DebugValueScope(null, globalMap), sortedValues); + LogStream log = getLogStream(options); + printMap(options, log, new DebugValueScope(null, globalMap), sortedValues); break; } case "Complete": { @@ -104,8 +105,8 @@ public class DebugValuesPrinter { } globalMap.group(); globalMap.normalize(); - LogStream log = getLogStream(); - printMap(log, new DebugValueScope(null, globalMap), sortedValues); + LogStream log = getLogStream(options); + printMap(options, log, new DebugValueScope(null, globalMap), sortedValues); break; } case "Thread": @@ -113,8 +114,8 @@ public class DebugValuesPrinter { TTY.println("Showing the results for thread: " + map.getName()); map.group(); map.normalize(); - LogStream log = getLogStream(map.getName().replace(' ', '_')); - printMap(log, new DebugValueScope(null, map), sortedValues); + LogStream log = getLogStream(options, map.getName().replace(' ', '_')); + printMap(options, log, new DebugValueScope(null, map), sortedValues); } break; default: @@ -136,12 +137,12 @@ public class DebugValuesPrinter { TTY.println(""); } - private static LogStream getLogStream() { - return getLogStream(null); + private static LogStream getLogStream(OptionValues options) { + return getLogStream(options, null); } - private static LogStream getLogStream(String prefix) { - String debugValueFile = DebugValueFile.getValue(); + private static LogStream getLogStream(OptionValues options, String prefix) { + String debugValueFile = DebugValueFile.getValue(options); if (debugValueFile != null) { try { final String fileName; @@ -168,7 +169,7 @@ public class DebugValuesPrinter { map.clearChildren(); } - private void printSummary(LogStream log, List topLevelMaps, List debugValues) { + private void printSummary(OptionValues options, LogStream log, List topLevelMaps, List debugValues) { DebugValueMap result = new DebugValueMap("Summary"); for (int i = debugValues.size() - 1; i >= 0; i--) { DebugValue debugValue = debugValues.get(i); @@ -176,7 +177,7 @@ public class DebugValuesPrinter { long total = collectTotal(topLevelMaps, index); result.setCurrentValue(index, total); } - printMap(log, new DebugValueScope(null, result), debugValues); + printMap(options, log, new DebugValueScope(null, result), debugValues); } private long collectTotal(List maps, int index) { @@ -228,19 +229,19 @@ public class DebugValuesPrinter { } - private void printMap(LogStream log, DebugValueScope scope, List debugValues) { - if (DebugValueHumanReadable.getValue()) { - printMapHumanReadable(log, scope, debugValues); + private void printMap(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { + if (DebugValueHumanReadable.getValue(options)) { + printMapHumanReadable(options, log, scope, debugValues); } else { - printMapComputerReadable(log, scope, debugValues); + printMapComputerReadable(options, log, scope, debugValues); } } - private void printMapComputerReadable(LogStream log, DebugValueScope scope, List debugValues) { + private void printMapComputerReadable(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { for (DebugValue value : debugValues) { long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue()) { + if (l != 0 || !SuppressZeroDebugValues.getValue(options)) { CSVUtil.Escape.println(log, COMPUTER_READABLE_FMT, scope.toRawString(), value.getName(), value.toRawString(l), value.rawUnit()); } } @@ -248,15 +249,15 @@ public class DebugValuesPrinter { List children = scope.map.getChildren(); for (int i = 0; i < children.size(); i++) { DebugValueMap child = children.get(i); - printMapComputerReadable(log, new DebugValueScope(scope, child), debugValues); + printMapComputerReadable(options, log, new DebugValueScope(scope, child), debugValues); } } - private void printMapHumanReadable(LogStream log, DebugValueScope scope, List debugValues) { + private void printMapHumanReadable(OptionValues options, LogStream log, DebugValueScope scope, List debugValues) { for (DebugValue value : debugValues) { long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue()) { + if (l != 0 || !SuppressZeroDebugValues.getValue(options)) { scope.print(log); printIndent(log, scope.level + 1); log.println(value.getName() + "=" + value.toString(l)); @@ -266,7 +267,7 @@ public class DebugValuesPrinter { List children = scope.map.getChildren(); for (int i = 0; i < children.size(); i++) { DebugValueMap child = children.get(i); - printMapHumanReadable(log, new DebugValueScope(scope, child), debugValues); + printMapHumanReadable(options, log, new DebugValueScope(scope, child), debugValues); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java index de653cac885..5f683f36778 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java @@ -201,7 +201,7 @@ public class MethodMetricsImpl implements DebugMethodMetrics { if (threadCache == null) { // this branch will only be executed once for each compiler thread on the first request // of a method metric - threadCache = new HashMap<>(GraalDebugConfig.Options.MethodFilter.getValue() == null ? 128 : 16); + threadCache = new HashMap<>(GraalDebugConfig.Options.MethodFilter.getValue(DebugScope.getConfig().getOptions()) == null ? 128 : 16); threadEntries.set(threadCache); addThreadCompilationData(threadCache); } @@ -334,7 +334,7 @@ public class MethodMetricsImpl implements DebugMethodMetrics { Set methods = new HashSet<>(); // gather all methods we found - threadMaps.stream().forEach(x -> { + threadMaps.forEach(x -> { // snapshot the current compilations to only capture all methods compiled until now HashMap snapShot = new HashMap<>(x); snapShot.keySet().forEach(y -> methods.add(y)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java index 11f82ab49e9..2d882d21d3b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.debug.internal.method; import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -34,15 +35,15 @@ public class MethodMetricsInlineeScopeInfo extends MethodMetricsRootScopeInfo { super(rootMethod); } - public static MethodMetricsInlineeScopeInfo create(ResolvedJavaMethod rootMethod) { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { + public static MethodMetricsInlineeScopeInfo create(ResolvedJavaMethod rootMethod, OptionValues options) { + if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { return new MethodMetricsInlineeScopeInfo(rootMethod); } return null; } - public static MethodMetricsInlineeScopeInfo create() { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { + public static MethodMetricsInlineeScopeInfo create(OptionValues options) { + if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled(options)) { ExtraInfo rootInfo = DebugScope.getInstance().getExtraInfo(); if (rootInfo instanceof MethodMetricsRootScopeInfo) { return new MethodMetricsInlineeScopeInfo(((MethodMetricsRootScopeInfo) rootInfo).getRootMethod()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java index e74ed661861..3ebf04cfac4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java @@ -33,9 +33,11 @@ import java.util.List; import org.graalvm.compiler.debug.DebugMethodMetrics; import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; /** * Interface for printing a collection of method metrics (e.g. during shutdown). @@ -45,14 +47,14 @@ public interface MethodMetricsPrinter { class Options { // @formatter:off @Option(help = "Dump method metrics to stdout on shutdown.", type = OptionType.Debug) - public static final OptionValue MethodMeterPrintAscii = new OptionValue<>(false); + public static final OptionKey MethodMeterPrintAscii = new OptionKey<>(false); @Option(help = "Dump method metrics to the given file in CSV format on shutdown.", type = OptionType.Debug) - public static final OptionValue MethodMeterFile = new OptionValue<>(null); + public static final OptionKey MethodMeterFile = new OptionKey<>(null); // @formatter:on } - static boolean methodMetricsDumpingEnabled() { - return MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue() || MethodMetricsPrinter.Options.MethodMeterFile.getValue() != null; + static boolean methodMetricsDumpingEnabled(OptionValues options) { + return MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue(options) || MethodMetricsPrinter.Options.MethodMeterFile.getValue(options) != null; } /** @@ -110,9 +112,9 @@ public interface MethodMetricsPrinter { public MethodMetricsCSVFilePrinter() { try { - fw = new FileOutputStream(new File(Options.MethodMeterFile.getValue())); + fw = new FileOutputStream(new File(Options.MethodMeterFile.getValue(DebugScope.getConfig().getOptions()))); } catch (IOException e) { - TTY.println("Cannot create file %s for method metrics dumping:%s", Options.MethodMeterFile.getValue(), e); + TTY.println("Cannot create file %s for method metrics dumping:%s", Options.MethodMeterFile.getValue(DebugScope.getConfig().getOptions()), e); throw new Error(e); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java index fd8b18d23d5..8667b1b86b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java @@ -54,11 +54,16 @@ public class MethodMetricsRootScopeInfo implements ExtraInfo { * is already an existing one on the scope */ public static Debug.Scope createRootScopeIfAbsent(ResolvedJavaMethod method) { - /* - * if the current compilation is not triggered from JVMCI we need a valid context root - * method for method metrics - */ - return DebugScope.getInstance().getExtraInfo() instanceof MethodMetricsRootScopeInfo ? null : Debug.methodMetricsScope("GraalCompilerRoot", MethodMetricsRootScopeInfo.create(method), true); + if (Debug.isEnabled()) { + /* + * if the current compilation is not triggered from JVMCI we need a valid context root + * method for method metrics + */ + return DebugScope.getInstance().getExtraInfo() instanceof MethodMetricsRootScopeInfo ? null + : Debug.methodMetricsScope("GraalCompilerRoot", MethodMetricsRootScopeInfo.create(method), true); + } else { + return null; + } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/data/DataList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java similarity index 74% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/data/DataList.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java index 1f5a96583d6..a064c75de60 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/data/DataList.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -20,11 +20,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.data; +package org.graalvm.compiler.graph.test; -import java.util.ArrayList; +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.options.OptionValues; -public class DataList extends ArrayList { +public abstract class GraphTest { - private static final long serialVersionUID = 1L; + static OptionValues getOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java index 8d23f55727f..265cf9550f2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java @@ -31,13 +31,14 @@ import org.junit.Before; import org.junit.Test; import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class NodeMapTest { +public class NodeMapTest extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class TestNode extends Node { @@ -57,7 +58,7 @@ public class NodeMapTest { // Need to initialize HotSpotGraalRuntime before any Node class is initialized. Graal.getRuntime(); - graph = new Graph(); + graph = new Graph(getOptions()); for (int i = 0; i < nodes.length; i++) { nodes[i] = graph.add(new TestNode()); } @@ -107,13 +108,6 @@ public class NodeMapTest { } } - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } - @Test public void testNewGet() { /* @@ -123,7 +117,7 @@ public class NodeMapTest { TestNode newNode = graph.add(new TestNode()); try { map.get(newNode); - fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); + fail("expected " + (Assertions.ENABLED ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); } catch (AssertionError ae) { // thrown when assertions are enabled } catch (ArrayIndexOutOfBoundsException e) { @@ -140,7 +134,7 @@ public class NodeMapTest { TestNode newNode = graph.add(new TestNode()); try { map.set(newNode, 1); - fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); + fail("expected " + (Assertions.ENABLED ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); } catch (AssertionError ae) { // thrown when assertions are enabled } catch (ArrayIndexOutOfBoundsException e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java index 2f8f34f82b0..35629047a0d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java @@ -37,7 +37,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class NodeUsagesTests { +public class NodeUsagesTests extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class Def extends Node { @@ -66,7 +66,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsages() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -95,7 +95,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicateAll() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -124,7 +124,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicateNone() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -153,7 +153,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate1() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -184,7 +184,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate2() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -215,7 +215,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate0() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -246,7 +246,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate02() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -277,7 +277,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate023() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -311,7 +311,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate013() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -345,7 +345,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate203() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -379,7 +379,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate01() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -410,7 +410,7 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate12() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java index 18d822d34ec..effdd7df305 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java @@ -33,7 +33,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class NodeValidationChecksTest { +public class NodeValidationChecksTest extends GraphTest { @NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) static final class TestNode extends Node { @@ -51,7 +51,7 @@ public class NodeValidationChecksTest { @Test public void testInputNotAlive() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(node, null)); @@ -64,7 +64,7 @@ public class NodeValidationChecksTest { @Test public void testSuccessorNotAlive() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(null, node)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java index 269143bbe33..8e34b5b65b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java @@ -33,14 +33,15 @@ import static org.junit.Assert.fail; import java.util.Iterator; import org.junit.Test; - +import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.options.OptionValues; -public class TypedNodeIteratorTest { +public class TypedNodeIteratorTest extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class TestNode extends Node implements IterableNodeType, TestNodeInterface { @@ -61,16 +62,21 @@ public class TypedNodeIteratorTest { @Test public void singleNodeTest() { - Graph graph = new Graph(); + getOptions(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); assertTrue(graph.hasNode(TestNode.TYPE)); assertEquals("a", toString(graph.getNodes(TestNode.TYPE))); } + static OptionValues getOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + @Test public void deletingNodeTest() { TestNode testNode = new TestNode("a"); - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(testNode); testNode.safeDelete(); assertEquals("", toString(graph.getNodes(TestNode.TYPE))); @@ -79,7 +85,7 @@ public class TypedNodeIteratorTest { @Test public void deleteAndAddTest() { TestNode testNode = new TestNode("b"); - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); graph.add(testNode); testNode.safeDelete(); @@ -90,7 +96,7 @@ public class TypedNodeIteratorTest { @Test public void iteratorBehaviorTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); Iterator iterator = graph.getNodes(TestNode.TYPE).iterator(); assertTrue(iterator.hasNext()); @@ -109,7 +115,7 @@ public class TypedNodeIteratorTest { @Test public void complicatedIterationTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); for (TestNode tn : graph.getNodes(TestNode.TYPE)) { String name = tn.getName(); @@ -148,7 +154,7 @@ public class TypedNodeIteratorTest { @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new TestNode("a")); StringBuilder sb = new StringBuilder(); int z = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java index c56b19c4b70..526a028fe56 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java @@ -36,7 +36,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class TypedNodeIteratorTest2 { +public class TypedNodeIteratorTest2 extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static class NodeA extends Node implements TestNodeInterface { @@ -99,7 +99,7 @@ public class TypedNodeIteratorTest2 { @Test public void simpleSubclassTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new NodeB("b")); graph.add(new NodeD("d")); @@ -109,7 +109,7 @@ public class TypedNodeIteratorTest2 { @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions()); graph.add(new NodeB("b1")); NodeD d1 = graph.add(new NodeD("d1")); StringBuilder sb = new StringBuilder(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml index f18b015c883..85607d1b5e4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml @@ -135,9 +135,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java index 42122975c5d..6d7b7468d5d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java @@ -22,9 +22,10 @@ */ package org.graalvm.compiler.graph; -import java.util.Map; import java.util.function.Consumer; +import org.graalvm.util.UnmodifiableEconomicMap; + /** * This class is a container of a graph that needs to be readonly and optionally a lazily created * mutable copy of the graph. @@ -59,7 +60,7 @@ public final class CachedGraph { } @SuppressWarnings("unchecked") - public G getMutableCopy(Consumer> duplicationMapCallback) { + public G getMutableCopy(Consumer> duplicationMapCallback) { if (!hasMutableCopy()) { mutableCopy = (G) readonlyCopy.copy(duplicationMapCallback); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java deleted file mode 100644 index 70da681313f..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.graph; - -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.api.collections.DefaultCollectionsProvider; - -/** - * A default implementation of {@link NodeCollectionsProvider} that creates standard JDK collection - * class objects. - */ -public class DefaultNodeCollectionsProvider extends DefaultCollectionsProvider implements NodeCollectionsProvider { - - @Override - public Set newNodeIdentitySet() { - return Collections.newSetFromMap(newNodeIdentityMap()); - } - - @Override - public Map newNodeIdentityMap() { - return new IdentityHashMap<>(); - } - - @Override - public Map newNodeIdentityMap(int expectedMaxSize) { - return new IdentityHashMap<>(expectedMaxSize); - } - - @Override - public Map newNodeIdentityMap(Map initFrom) { - return new IdentityHashMap<>(initFrom); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java index 4c36413e06c..0e7edffcec6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java @@ -71,11 +71,11 @@ public abstract class Edges extends Fields { return (NodeList) UNSAFE.getObject(node, offset); } - private static void putNodeUnsafe(Node node, long offset, Node value) { + public static void putNodeUnsafe(Node node, long offset, Node value) { UNSAFE.putObject(node, offset, value); } - private static void putNodeListUnsafe(Node node, long offset, NodeList value) { + public static void putNodeListUnsafe(Node node, long offset, NodeList value) { UNSAFE.putObject(node, offset, value); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java index 8e99606de1d..3fa5fd0387e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,25 +22,28 @@ */ package org.graalvm.compiler.graph; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.function.Consumer; - -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.Fingerprint; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ValueNumberable; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; +import org.graalvm.util.UnmodifiableEconomicMap; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.function.Consumer; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; /** * This class is a graph container, it contains the set of nodes that belong to this graph. @@ -49,13 +52,17 @@ public class Graph { public static class Options { @Option(help = "Verify graphs often during compilation when assertions are turned on", type = OptionType.Debug)// - public static final OptionValue VerifyGraalGraphs = new OptionValue<>(true); + public static final OptionKey VerifyGraalGraphs = new OptionKey<>(true); @Option(help = "Perform expensive verification of graph inputs, usages, successors and predecessors", type = OptionType.Debug)// - public static final OptionValue VerifyGraalGraphEdges = new OptionValue<>(false); + public static final OptionKey VerifyGraalGraphEdges = new OptionKey<>(false); @Option(help = "Graal graph compression is performed when percent of live nodes falls below this value", type = OptionType.Debug)// - public static final OptionValue GraphCompressionThreshold = new OptionValue<>(70); - @Option(help = "Use Unsafe to clone graph nodes thus avoiding copying fields that will be re-initialized anyway", type = OptionType.Debug)// - public static final OptionValue CloneNodesWithUnsafe = new OptionValue<>(true); + public static final OptionKey GraphCompressionThreshold = new OptionKey<>(70); + } + + private enum FreezeState { + Unfrozen, + TemporaryFreeze, + DeepFreeze } public final String name; @@ -109,51 +116,36 @@ public class Graph { * Used to global value number {@link ValueNumberable} {@linkplain NodeClass#isLeafNode() leaf} * nodes. */ - private final HashMap cachedLeafNodes = CollectionsFactory.newMap(); + private EconomicMap[] cachedLeafNodes; - /* - * Indicates that the graph should no longer be modified. Frozen graphs can be used my multiple - * threads so it's only safe to read them. - */ - private boolean isFrozen = false; - - /** - * Entry in {@link Graph#cachedLeafNodes}. - */ - private static final class CacheEntry { - - private final Node node; - - CacheEntry(Node node) { - assert node.getNodeClass().valueNumberable(); - assert node.getNodeClass().isLeafNode(); - this.node = node; - } + private static final Equivalence NODE_VALUE_COMPARE = new Equivalence() { @Override - public int hashCode() { - return node.getNodeClass().valueNumber(node); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { + public boolean equals(Object a, Object b) { + if (a == b) { return true; } - if (obj instanceof CacheEntry) { - CacheEntry other = (CacheEntry) obj; - if (other.node.getClass() == node.getClass()) { - return node.valueEquals(other.node); - } - } - return false; + + assert a.getClass() == b.getClass(); + return ((Node) a).valueEquals((Node) b); } @Override - public String toString() { - return node.toString(); + public int hashCode(Object k) { + return ((Node) k).getNodeClass().valueNumber((Node) k); } - } + }; + + /** + * Indicates that the graph should no longer be modified. Frozen graphs can be used by multiple + * threads so it's only safe to read them. + */ + private FreezeState freezeState = FreezeState.Unfrozen; + + /** + * The option values used while compiling this graph. + */ + private final OptionValues options; private class NodeSourcePositionScope implements DebugCloseable { private final NodeSourcePosition previous; @@ -225,8 +217,8 @@ public class Graph { /** * Creates an empty Graph with no name. */ - public Graph() { - this(null); + public Graph(OptionValues options) { + this(null, options); } /** @@ -247,11 +239,13 @@ public class Graph { * * @param name the name of the graph, used for debugging purposes */ - public Graph(String name) { + public Graph(String name, OptionValues options) { nodes = new Node[INITIAL_NODES_SIZE]; iterableNodesFirst = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); iterableNodesLast = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); this.name = name; + this.options = options; + if (isModificationCountsEnabled()) { nodeModCounts = new int[INITIAL_NODES_SIZE]; nodeUsageModCounts = new int[INITIAL_NODES_SIZE]; @@ -318,7 +312,7 @@ public class Graph { * * @param duplicationMapCallback consumer of the duplication map created during the copying */ - public final Graph copy(Consumer> duplicationMapCallback) { + public final Graph copy(Consumer> duplicationMapCallback) { return copy(name, duplicationMapCallback); } @@ -337,15 +331,19 @@ public class Graph { * @param newName the name of the copy, used for debugging purposes (can be null) * @param duplicationMapCallback consumer of the duplication map created during the copying */ - protected Graph copy(String newName, Consumer> duplicationMapCallback) { - Graph copy = new Graph(newName); - Map duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (Map) null); + protected Graph copy(String newName, Consumer> duplicationMapCallback) { + Graph copy = new Graph(newName, options); + UnmodifiableEconomicMap duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (EconomicMap) null); if (duplicationMapCallback != null) { duplicationMapCallback.accept(duplicates); } return copy; } + public final OptionValues getOptions() { + return options; + } + @Override public String toString() { return name == null ? super.toString() : "Graph " + name; @@ -404,22 +402,30 @@ public class Graph { public T addOrUnique(T node) { if (node.getNodeClass().valueNumberable()) { - return uniqueHelper(node, true); + return uniqueHelper(node); } return add(node); } - public T addWithoutUniqueWithInputs(T node) { - addInputs(node); - return addHelper(node); + public T maybeAddOrUnique(T node) { + if (node.isAlive()) { + return node; + } + return addOrUnique(node); } public T addOrUniqueWithInputs(T node) { - addInputs(node); - if (node.getNodeClass().valueNumberable()) { - return uniqueHelper(node, true); + if (node.isAlive()) { + assert node.graph() == this; + return node; + } else { + assert node.isUnregistered(); + addInputs(node); + if (node.getNodeClass().valueNumberable()) { + return uniqueHelper(node); + } + return add(node); } - return add(node); } private final class AddInputsFilter extends Node.EdgeVisitor { @@ -583,16 +589,16 @@ public class Graph { * @return a node similar to {@code node} if one exists, otherwise {@code node} */ public T unique(T node) { - return uniqueHelper(node, true); + return uniqueHelper(node); } - T uniqueHelper(T node, boolean addIfMissing) { + T uniqueHelper(T node) { assert node.getNodeClass().valueNumberable(); T other = this.findDuplicate(node); if (other != null) { return other; } else { - T result = addIfMissing ? addHelper(node) : node; + T result = addHelper(node); if (node.getNodeClass().isLeafNode()) { putNodeIntoCache(result); } @@ -600,21 +606,47 @@ public class Graph { } } + void removeNodeFromCache(Node node) { + assert node.graph() == this || node.graph() == null; + assert node.getNodeClass().valueNumberable(); + assert node.getNodeClass().isLeafNode() : node.getClass(); + + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes != null && cachedLeafNodes.length > leafId && cachedLeafNodes[leafId] != null) { + cachedLeafNodes[leafId].removeKey(node); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) void putNodeIntoCache(Node node) { assert node.graph() == this || node.graph() == null; assert node.getNodeClass().valueNumberable(); assert node.getNodeClass().isLeafNode() : node.getClass(); - CacheEntry entry = new CacheEntry(node); - cachedLeafNodes.put(entry, node); + + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes == null || cachedLeafNodes.length <= leafId) { + EconomicMap[] newLeafNodes = new EconomicMap[leafId + 1]; + if (cachedLeafNodes != null) { + System.arraycopy(cachedLeafNodes, 0, newLeafNodes, 0, cachedLeafNodes.length); + } + cachedLeafNodes = newLeafNodes; + } + + if (cachedLeafNodes[leafId] == null) { + cachedLeafNodes[leafId] = EconomicMap.create(NODE_VALUE_COMPARE); + } + + cachedLeafNodes[leafId].put(node, node); } Node findNodeInCache(Node node) { - CacheEntry key = new CacheEntry(node); - Node result = cachedLeafNodes.get(key); - if (result != null && result.isDeleted()) { - cachedLeafNodes.remove(key); + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes == null || cachedLeafNodes.length <= leafId || cachedLeafNodes[leafId] == null) { return null; } + + Node result = cachedLeafNodes[leafId].get(node); + assert result == null || result.isAlive() : result; return result; } @@ -763,7 +795,7 @@ public class Graph { } // Fully qualified annotation name is required to satisfy javac - @org.graalvm.compiler.nodeinfo.NodeInfo + @org.graalvm.compiler.nodeinfo.NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class PlaceHolderNode extends Node { public static final NodeClass TYPE = NodeClass.create(PlaceHolderNode.class); @@ -774,16 +806,12 @@ public class Graph { } - static final Node PLACE_HOLDER = new PlaceHolderNode(); - - public static final int COMPRESSION_THRESHOLD = Options.GraphCompressionThreshold.getValue(); - private static final DebugCounter GraphCompressions = Debug.counter("GraphCompressions"); /** - * If the {@linkplain #COMPRESSION_THRESHOLD compression threshold} is met, the list of nodes is - * compressed such that all non-null entries precede all null entries while preserving the - * ordering between the nodes within the list. + * If the {@linkplain Options#GraphCompressionThreshold compression threshold} is met, the list + * of nodes is compressed such that all non-null entries precede all null entries while + * preserving the ordering between the nodes within the list. */ public boolean maybeCompress() { if (Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod()) { @@ -791,7 +819,8 @@ public class Graph { } int liveNodeCount = getNodeCount(); int liveNodePercent = liveNodeCount * 100 / nodesSize; - if (COMPRESSION_THRESHOLD == 0 || liveNodePercent >= COMPRESSION_THRESHOLD) { + int compressionThreshold = Options.GraphCompressionThreshold.getValue(options); + if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) { return false; } GraphCompressions.increment(); @@ -937,31 +966,33 @@ public class Graph { assert !isFrozen(); assert node.id() == Node.INITIAL_ID; if (nodes.length == nodesSize) { - Node[] newNodes = new Node[(nodesSize * 2) + 1]; - System.arraycopy(nodes, 0, newNodes, 0, nodesSize); - nodes = newNodes; + grow(); } - int id = nodesSize; + int id = nodesSize++; nodes[id] = node; + node.id = id; if (currentNodeSourcePosition != null) { node.setNodeSourcePosition(currentNodeSourcePosition); - } else if (!seenNodeSourcePosition && node.getNodeSourcePosition() != null) { - seenNodeSourcePosition = true; } - nodesSize++; + seenNodeSourcePosition = seenNodeSourcePosition || node.getNodeSourcePosition() != null; updateNodeCaches(node); - node.id = id; if (nodeEventListener != null) { nodeEventListener.nodeAdded(node); } - if (!seenNodeSourcePosition && node.sourcePosition != null) { - seenNodeSourcePosition = true; - } - if (Fingerprint.ENABLED) { - Fingerprint.submit("%s: %s", NodeEvent.NODE_ADDED, node); - } + afterRegister(node); + } + + private void grow() { + Node[] newNodes = new Node[(nodesSize * 2) + 1]; + System.arraycopy(nodes, 0, newNodes, 0, nodesSize); + nodes = newNodes; + } + + @SuppressWarnings("unused") + protected void afterRegister(Node node) { + } @SuppressWarnings("unused") @@ -1003,7 +1034,10 @@ public class Graph { void unregister(Node node) { assert !isFrozen(); - assert !node.isDeleted() : "cannot delete a node twice! node=" + node; + assert !node.isDeleted() : node; + if (node.getNodeClass().isLeafNode() && node.getNodeClass().valueNumberable()) { + removeNodeFromCache(node); + } nodes[node.id] = null; nodesDeletedSinceLastCompression++; @@ -1011,7 +1045,7 @@ public class Graph { } public boolean verify() { - if (Options.VerifyGraalGraphs.getValue()) { + if (Options.VerifyGraalGraphs.getValue(options)) { for (Node node : getNodes()) { try { try { @@ -1053,7 +1087,7 @@ public class Graph { * @param replacementsMap the replacement map (can be null if no replacement is to be performed) * @return a map which associates the original nodes from {@code nodes} to their duplicates */ - public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, Map replacementsMap) { + public UnmodifiableEconomicMap addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, EconomicMap replacementsMap) { DuplicationReplacement replacements; if (replacementsMap == null) { replacements = null; @@ -1070,9 +1104,9 @@ public class Graph { private static final class MapReplacement implements DuplicationReplacement { - private final Map map; + private final EconomicMap map; - MapReplacement(Map map) { + MapReplacement(EconomicMap map) { this.map = map; } @@ -1087,27 +1121,31 @@ public class Graph { private static final DebugTimer DuplicateGraph = Debug.timer("DuplicateGraph"); @SuppressWarnings({"all", "try"}) - public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { + public EconomicMap addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { try (DebugCloseable s = DuplicateGraph.start()) { return NodeClass.addGraphDuplicate(this, oldGraph, estimatedNodeCount, newNodes, replacements); } } - /** - * Reverses the usage orders of all nodes. This is used for debugging to make sure an unorthodox - * usage order does not trigger bugs in the compiler. - */ - public void reverseUsageOrder() { - for (Node n : getNodes()) { - n.reverseUsageOrder(); - } - } - public boolean isFrozen() { - return isFrozen; + return freezeState != FreezeState.Unfrozen; } public void freeze() { - this.isFrozen = true; + this.freezeState = FreezeState.DeepFreeze; + } + + public void temporaryFreeze() { + if (this.freezeState == FreezeState.DeepFreeze) { + throw new GraalError("Graph was permanetly frozen."); + } + this.freezeState = FreezeState.TemporaryFreeze; + } + + public void unfreeze() { + if (this.freezeState == FreezeState.DeepFreeze) { + throw new GraalError("Graph was permanetly frozen."); + } + this.freezeState = FreezeState.Unfrozen; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index 14ebbd82f08..025fb38c5a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -29,24 +29,20 @@ import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; -import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.function.Predicate; -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.core.common.Fields; +import org.graalvm.compiler.core.common.type.AbstractPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.Fingerprint; -import org.graalvm.compiler.graph.Graph.NodeEvent; import org.graalvm.compiler.graph.Graph.NodeEventListener; import org.graalvm.compiler.graph.Graph.Options; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -54,8 +50,11 @@ import org.graalvm.compiler.graph.iterators.NodePredicate; import org.graalvm.compiler.graph.spi.Simplifiable; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.options.OptionValues; import sun.misc.Unsafe; @@ -71,21 +70,6 @@ import sun.misc.Unsafe; *

    * Nodes which are be value numberable should implement the {@link ValueNumberable} interface. * - *

    Replay Compilation

    - * - * To enable deterministic replay compilation, node sets and node maps should be instantiated with - * the following methods: - *
      - *
    • {@link #newSet()}
    • - *
    • {@link #newSet(Collection)}
    • - *
    • {@link #newMap()}
    • - *
    • {@link #newMap(int)}
    • - *
    • {@link #newMap(Map)}
    • - *
    • {@link #newIdentityMap()}
    • - *
    • {@link #newIdentityMap(int)}
    • - *
    • {@link #newIdentityMap(Map)}
    • - *
    - * *

    Assertions and Verification

    * * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and @@ -98,7 +82,7 @@ import sun.misc.Unsafe; public abstract class Node implements Cloneable, Formattable, NodeInterface { public static final NodeClass TYPE = null; - public static final boolean USE_UNSAFE_TO_CLONE = Graph.Options.CloneNodesWithUnsafe.getValue(); + public static final boolean USE_UNSAFE_TO_CLONE = true; static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; @@ -149,7 +133,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { * Denotes an injected parameter in a {@linkplain NodeIntrinsic node intrinsic} constructor. If * the constructor is called as part of node intrinsification, the node intrinsifier will inject * an argument for the annotated parameter. Injected parameters must precede all non-injected - * parameters in a constructor. + * parameters in a constructor. If the type of the annotated parameter is {@link Stamp}, the + * {@linkplain Stamp#javaType type} of the injected stamp is the return type of the annotated + * method (which cannot be {@code void}). */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.PARAMETER) @@ -158,40 +144,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { /** * Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the - * annotated method can be replaced with an instance of the node class denoted by - * {@link #value()}. For this reason, the signature of the annotated method must match the - * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a - * constructor in the node class. + * annotated method will be processed by a generated {@code InvocationPlugin} that calls either + * a factory method or a constructor corresponding with the annotated method. *

    - * If the node class has a static method {@code intrinsify} with a matching signature plus a - * {@code GraphBuilderContext} as first argument, this method is called instead of creating the - * node. + * A factory method corresponding to an annotated method is a static method named + * {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature + * is as follows: + *

      + *
    1. A {@code GraphBuilderContext} parameter.
    2. + *
    3. A {@code ResolvedJavaMethod} parameter.
    4. + *
    5. A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.
    6. + *
    7. Remaining parameters that match the declared parameters of the annotated method.
    8. + *
    + * A constructor corresponding to an annotated method is defined in the class denoted by + * {@link #value()}. In order, its signature is as follows: + *
      + *
    1. A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.
    2. + *
    3. Remaining parameters that match the declared parameters of the annotated method.
    4. + *
    + * There must be exactly one such factory method or constructor corresponding to a + * {@link NodeIntrinsic} annotated method. */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.METHOD) public static @interface NodeIntrinsic { /** - * Gets the {@link Node} subclass instantiated when intrinsifying a call to the annotated - * method. If not specified, then the class in which the annotated method is declared is - * used (and is assumed to be a {@link Node} subclass). + * The class declaring the factory method or {@link Node} subclass declaring the constructor + * used to intrinsify a call to the annotated method. The default value is the class in + * which the annotated method is declared. */ Class value() default NodeIntrinsic.class; /** - * Determines if the stamp of the instantiated intrinsic node has its stamp set from the - * return type of the annotated method. - *

    - * When it is set to true, the stamp that is passed in to the constructor of ValueNode is - * ignored and can therefore safely be {@code null}. + * If {@code true}, the factory method or constructor selected by the annotation must have + * an {@linkplain InjectedNodeParameter injected} {@link Stamp} parameter. Calling + * {@link AbstractPointerStamp#nonNull()} on the injected stamp is guaranteed to return + * {@code true}. */ - boolean setStampFromReturnType() default false; - - /** - * Determines if the stamp of the instantiated intrinsic node is guaranteed to be non-null. - * Generally used in conjunction with {@link #setStampFromReturnType()}. - */ - boolean returnStampIsNonNull() default false; + boolean injectedStampIsNonNull() default false; } /** @@ -257,56 +248,6 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return this; } - /** - * @see CollectionsFactory#newSet() - */ - public static Set newSet() { - return CollectionsFactory.newSet(); - } - - /** - * @see #newSet() - */ - public static Set newSet(Collection c) { - return CollectionsFactory.newSet(c); - } - - public static Map newMap() { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(); - } - - public static Map newMap(Map m) { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(m); - } - - public static Map newMap(int expectedMaxSize) { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(expectedMaxSize); - } - - public static Map newIdentityMap() { - return CollectionsFactory.newIdentityMap(); - } - - public static Map newIdentityMap(Map m) { - return CollectionsFactory.newIdentityMap(m); - } - - public static Map newIdentityMap(int expectedMaxSize) { - return CollectionsFactory.newIdentityMap(expectedMaxSize); - } - /** * Gets the graph context of this node. */ @@ -314,6 +255,13 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return graph; } + /** + * Gets the option values associated with this node's graph. + */ + public final OptionValues getOptions() { + return graph == null ? null : graph.getOptions(); + } + /** * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input * edges of this node. @@ -365,7 +313,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { * @return an {@link NodeIterable iterable} for all non-null successor edges. */ public NodeIterable successors() { - assert !this.isDeleted(); + assert !this.isDeleted() : this; return nodeClass.getSuccessorIterable(this); } @@ -389,7 +337,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (usage1 == null) { return 1; } - return 2 + extraUsagesCount; + return INLINE_USAGE_COUNT + extraUsagesCount; } /** @@ -413,15 +361,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return this.usage0 != null; } - void reverseUsageOrder() { - List snapshot = this.usages().snapshot(); - for (Node n : snapshot) { - this.removeUsage(n); - } - Collections.reverse(snapshot); - for (Node n : snapshot) { - this.addUsage(n); - } + /** + * Checks whether this node has more than one usages. + */ + public final boolean hasMoreThanOneUsage() { + return this.usage1 != null; + } + + /** + * Checks whether this node has exactly one usgae. + */ + public final boolean hasExactlyOneUsage() { + return hasUsages() && !hasMoreThanOneUsage(); } /** @@ -449,30 +400,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } private void movUsageFromEndTo(int destIndex) { - int lastIndex = this.getUsageCount() - 1; - if (destIndex == 0) { - if (lastIndex == 0) { - usage0 = null; - return; - } else if (lastIndex == 1) { - usage0 = usage1; - usage1 = null; - return; - } else { - usage0 = extraUsages[lastIndex - INLINE_USAGE_COUNT]; - } + if (destIndex >= INLINE_USAGE_COUNT) { + movUsageFromEndToExtraUsages(destIndex - INLINE_USAGE_COUNT); } else if (destIndex == 1) { - if (lastIndex == 1) { - usage1 = null; - return; - } - usage1 = extraUsages[lastIndex - INLINE_USAGE_COUNT]; + movUsageFromEndToIndexOne(); } else { - Node n = extraUsages[lastIndex - INLINE_USAGE_COUNT]; - extraUsages[destIndex - INLINE_USAGE_COUNT] = n; + assert destIndex == 0; + movUsageFromEndToIndexZero(); } - extraUsages[lastIndex - INLINE_USAGE_COUNT] = null; + } + + private void movUsageFromEndToExtraUsages(int destExtraIndex) { this.extraUsagesCount--; + Node n = extraUsages[extraUsagesCount]; + extraUsages[destExtraIndex] = n; + extraUsages[extraUsagesCount] = null; + } + + private void movUsageFromEndToIndexZero() { + if (extraUsagesCount > 0) { + this.extraUsagesCount--; + usage0 = extraUsages[extraUsagesCount]; + extraUsages[extraUsagesCount] = null; + } else if (usage1 != null) { + usage0 = usage1; + usage1 = null; + } else { + usage0 = null; + } + } + + private void movUsageFromEndToIndexOne() { + if (extraUsagesCount > 0) { + this.extraUsagesCount--; + usage1 = extraUsages[extraUsagesCount]; + extraUsages[extraUsagesCount] = null; + } else { + assert usage1 != null; + usage1 = null; + } } /** @@ -483,20 +449,21 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { */ public boolean removeUsage(Node node) { assert node != null; - // It is critical that this method maintains the invariant that - // the usage list has no null element preceding a non-null element + // For large graphs, usage removal is performance critical. + // Furthermore, it is critical that this method maintains the invariant that the usage list + // has no null element preceding a non-null element. incUsageModCount(); if (usage0 == node) { - this.movUsageFromEndTo(0); + movUsageFromEndToIndexZero(); return true; } if (usage1 == node) { - this.movUsageFromEndTo(1); + movUsageFromEndToIndexOne(); return true; } for (int i = this.extraUsagesCount - 1; i >= 0; i--) { if (extraUsages[i] == node) { - this.movUsageFromEndTo(i + INLINE_USAGE_COUNT); + movUsageFromEndToExtraUsages(i); return true; } } @@ -533,14 +500,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } } - public boolean isDeleted() { + public final boolean isDeleted() { return id <= DELETED_ID_START; } - public boolean isAlive() { + public final boolean isAlive() { return id >= ALIVE_ID_START; } + public final boolean isUnregistered() { + return id == INITIAL_ID; + } + /** * Updates the usages sets of the given nodes after an input slot is changed from * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and @@ -591,8 +562,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id); this.graph = newGraph; newGraph.register(this); - this.getNodeClass().registerAtInputsAsUsage(this); - this.getNodeClass().registerAtSuccessorsAsPredecessor(this); + NodeClass nc = nodeClass; + nc.registerAtInputsAsUsage(this); + nc.registerAtSuccessorsAsPredecessor(this); } /** @@ -634,15 +606,23 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } private boolean checkReplaceWith(Node other) { - assert assertTrue(graph == null || !graph.isFrozen(), "cannot modify frozen graph"); - assert assertFalse(other == this, "cannot replace a node with itself"); - assert assertFalse(isDeleted(), "cannot replace deleted node"); - assert assertTrue(other == null || !other.isDeleted(), "cannot replace with deleted node %s", other); + if (graph != null && graph.isFrozen()) { + fail("cannot modify frozen graph"); + } + if (other == this) { + fail("cannot replace a node with itself"); + } + if (isDeleted()) { + fail("cannot replace deleted node"); + } + if (other != null && other.isDeleted()) { + fail("cannot replace with deleted node %s", other); + } return true; } public final void replaceAtUsages(Node other) { - replaceAtUsages(other, null, null); + replaceAtAllUsages(other, (Node) null); } public final void replaceAtUsages(Node other, Predicate filter) { @@ -660,22 +640,62 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } protected void replaceAtUsages(Node other, Predicate filter, Node toBeDeleted) { - assert checkReplaceWith(other); + if (filter == null) { + replaceAtAllUsages(other, toBeDeleted); + } else { + replaceAtMatchingUsages(other, filter, toBeDeleted); + } + } + + protected void replaceAtAllUsages(Node other, Node toBeDeleted) { + checkReplaceWith(other); + if (usage0 == null) { + return; + } + replaceAtUsage(other, toBeDeleted, usage0); + usage0 = null; + + if (usage1 == null) { + return; + } + replaceAtUsage(other, toBeDeleted, usage1); + usage1 = null; + + if (extraUsagesCount <= 0) { + return; + } + for (int i = 0; i < extraUsagesCount; i++) { + Node usage = extraUsages[i]; + replaceAtUsage(other, toBeDeleted, usage); + } + this.extraUsages = NO_NODES; + this.extraUsagesCount = 0; + } + + private void replaceAtUsage(Node other, Node toBeDeleted, Node usage) { + boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); + assert assertTrue(result, "not found in inputs, usage: %s", usage); + /* + * Don't notify for nodes which are about to be deleted. + */ + if (toBeDeleted == null || usage != toBeDeleted) { + maybeNotifyInputChanged(usage); + } + if (other != null) { + other.addUsage(usage); + } + } + + private void replaceAtMatchingUsages(Node other, Predicate filter, Node toBeDeleted) { + if (filter == null) { + fail("filter cannot be null"); + } + checkReplaceWith(other); int i = 0; while (i < this.getUsageCount()) { Node usage = this.getUsageAt(i); - if (filter == null || filter.test(usage)) { - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); - assert assertTrue(result, "not found in inputs, usage: %s", usage); - /* - * Don't notify for nodes which are about to be deleted. - */ - if (toBeDeleted == null || usage != toBeDeleted) { - maybeNotifyInputChanged(usage); - } - if (other != null) { - other.addUsage(usage); - } + if (filter.test(usage)) { + replaceAtUsage(other, toBeDeleted, usage); this.movUsageFromEndTo(i); } else { ++i; @@ -694,26 +714,12 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) { - assert checkReplaceWith(other); - int index = 0; - while (index < this.getUsageCount()) { - Node usage = getUsageAt(index); - if (usagePredicate.apply(usage)) { - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); - assert assertTrue(result, "not found in inputs, usage: %s", usage); - if (other != null) { - maybeNotifyInputChanged(usage); - other.addUsage(usage); - } - this.movUsageFromEndTo(index); - } else { - index++; - } - } + checkReplaceWith(other); + replaceAtMatchingUsages(other, usagePredicate, null); } public void replaceAtUsages(InputType type, Node other) { - assert checkReplaceWith(other); + checkReplaceWith(other); for (Node usage : usages().snapshot()) { for (Position pos : usage.inputPositions()) { if (pos.getInputType() == type && pos.get(usage) == this) { @@ -730,9 +736,6 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (listener != null) { listener.inputChanged(node); } - if (Fingerprint.ENABLED) { - Fingerprint.submit("%s: %s", NodeEvent.INPUT_CHANGED, node); - } } } @@ -743,25 +746,27 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (listener != null && node.isAlive()) { listener.usagesDroppedToZero(node); } - if (Fingerprint.ENABLED) { - Fingerprint.submit("%s: %s", NodeEvent.ZERO_USAGES, node); - } } } public void replaceAtPredecessor(Node other) { - assert checkReplaceWith(other); + checkReplaceWith(other); if (predecessor != null) { - boolean result = predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other); - assert assertTrue(result, "not found in successors, predecessor: %s", predecessor); + if (!predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other)) { + fail("not found in successors, predecessor: %s", predecessor); + } predecessor.updatePredecessor(this, other); } } public void replaceAndDelete(Node other) { - assert checkReplaceWith(other); - assert other != null; - replaceAtUsages(other); + checkReplaceWith(other); + if (other == null) { + fail("cannot replace with null"); + } + if (this.hasUsages()) { + replaceAtUsages(other); + } replaceAtPredecessor(other); this.safeDelete(); } @@ -852,12 +857,8 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (edgesToCopy.contains(type)) { getNodeClass().getEdges(type).copy(this, newNode); } else { - if (USE_UNSAFE_TO_CLONE) { - // The direct edges are already null - getNodeClass().getEdges(type).initializeLists(newNode, this); - } else { - getNodeClass().getEdges(type).clear(newNode); - } + // The direct edges are already null + getNodeClass().getEdges(type).initializeLists(newNode, this); } } @@ -891,22 +892,11 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { Node newNode = null; try { - if (USE_UNSAFE_TO_CLONE) { - newNode = (Node) UNSAFE.allocateInstance(getClass()); - newNode.nodeClass = nodeClassTmp; - nodeClassTmp.getData().copy(this, newNode); - copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); - copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); - } else { - newNode = (Node) this.clone(); - newNode.typeCacheNext = null; - newNode.usage0 = null; - newNode.usage1 = null; - newNode.predecessor = null; - newNode.extraUsagesCount = 0; - copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); - copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); - } + newNode = (Node) UNSAFE.allocateInstance(getClass()); + newNode.nodeClass = nodeClassTmp; + nodeClassTmp.getData().copy(this, newNode); + copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); + copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); } catch (Exception e) { throw new GraalGraphError(e).addContext(this); } @@ -936,7 +926,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (input == null) { assertTrue(pos.isInputOptional(), "non-optional input %s cannot be null in %s (fix nullness or use @OptionalInput)", pos, this); } else { - assertFalse(input.isDeleted(), "input was deleted"); + assertFalse(input.isDeleted(), "input was deleted %s", input); assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph"); assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType()); } @@ -948,7 +938,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); verifyInputs(); - if (Options.VerifyGraalGraphEdges.getValue()) { + if (Options.VerifyGraalGraphEdges.getValue(getOptions())) { verifyEdges(); } return true; @@ -1028,20 +1018,23 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } /** - * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code. + * Nodes using their {@link #id} as the hash code. This works very well when nodes of the same + * graph are stored in sets. It can give bad behavior when storing nodes of different graphs in + * the same set. */ @Override public final int hashCode() { - return System.identityHashCode(this); + assert !this.isUnregistered() : "node not yet constructed"; + if (this.isDeleted()) { + return -id + DELETED_ID_START; + } + return id; } /** - * Equality tests must rely solely on identity. + * Do not overwrite the equality test of a node in subclasses. Equality tests must rely solely + * on identity. */ - @Override - public final boolean equals(Object obj) { - return super.equals(obj); - } /** * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the @@ -1187,4 +1180,13 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { public final void pushInputs(NodeStack stack) { getNodeClass().pushInputs(this, stack); } + + public NodeSize estimatedNodeSize() { + return nodeClass.size(); + } + + public NodeCycles estimatedNodeCycles() { + return nodeClass.cycles(); + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java index b8333e3d9f9..6f27c243b92 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java @@ -154,7 +154,7 @@ public final class NodeBitMap implements NodeIterable { if (bits.length < other.bits.length) { bits = Arrays.copyOf(bits, other.bits.length); } - for (int i = 0; i < bits.length; i++) { + for (int i = 0; i < Math.min(bits.length, other.bits.length); i++) { bits[i] |= other.bits[i]; } } @@ -181,44 +181,47 @@ public final class NodeBitMap implements NodeIterable { } } - private static class MarkedNodeIterator implements Iterator { + protected int nextMarkedNodeId(int fromNodeId) { + assert fromNodeId >= 0; + int wordIndex = fromNodeId >> SHIFT; + int wordsInUse = bits.length; + if (wordIndex < wordsInUse) { + long word = bits[wordIndex] & (0xFFFFFFFFFFFFFFFFL << fromNodeId); + while (true) { + if (word != 0) { + return wordIndex * Long.SIZE + Long.numberOfTrailingZeros(word); + } + if (++wordIndex == wordsInUse) { + break; + } + word = bits[wordIndex]; + } + } + return -2; + } - private final NodeBitMap visited; - private Iterator nodes; - private Node nextNode; + private class MarkedNodeIterator implements Iterator { + private int nextNodeId; - MarkedNodeIterator(NodeBitMap visited, Iterator nodes) { - this.visited = visited; - this.nodes = nodes; + MarkedNodeIterator() { + nextNodeId = -1; forward(); } private void forward() { - do { - if (!nodes.hasNext()) { - nextNode = null; - return; - } - nextNode = nodes.next(); - if (visited.isNew(nextNode)) { - nextNode = null; - return; - } - } while (!visited.isMarked(nextNode)); + nextNodeId = NodeBitMap.this.nextMarkedNodeId(nextNodeId + 1); } @Override public boolean hasNext() { - return nextNode != null; + return nextNodeId >= 0; } @Override public Node next() { - try { - return nextNode; - } finally { - forward(); - } + Node result = graph.getNode(nextNodeId); + forward(); + return result; } @Override @@ -230,7 +233,7 @@ public final class NodeBitMap implements NodeIterable { @Override public Iterator iterator() { - return new MarkedNodeIterator(NodeBitMap.this, graph().getNodes().iterator()); + return new MarkedNodeIterator(); } public NodeBitMap copy() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java index b802b321e79..84be63bf75f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java @@ -28,7 +28,6 @@ import static org.graalvm.compiler.graph.Edges.translateInto; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.InputEdges.translateInto; import static org.graalvm.compiler.graph.Node.WithAllEdges; -import static org.graalvm.compiler.graph.Node.newIdentityMap; import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.lang.annotation.Annotation; @@ -39,7 +38,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.Iterator; -import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; @@ -51,7 +49,6 @@ import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.Fingerprint; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Edges.Type; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; @@ -68,9 +65,8 @@ import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Metadata for every {@link Node} type. The metadata includes: @@ -82,13 +78,6 @@ import org.graalvm.compiler.options.StableOptionValue; */ public final class NodeClass extends FieldIntrospection { - public static class Options { - // @formatter:off - @Option(help = "Verifies that receivers of NodeInfo#size() and NodeInfo#cycles() do not have UNSET values.") - public static final OptionValue VerifyNodeCostOnAccess = new StableOptionValue<>(false); - // @formatter:on - } - // Timers for creation of a NodeClass instance private static final DebugTimer Init_FieldScanning = Debug.timer("NodeClass.Init.FieldScanning"); private static final DebugTimer Init_FieldScanningInner = Debug.timer("NodeClass.Init.FieldScanning.Inner"); @@ -140,6 +129,7 @@ public final class NodeClass extends FieldIntrospection { private static final Class SUCCESSOR_LIST_CLASS = NodeSuccessorList.class; private static AtomicInteger nextIterableId = new AtomicInteger(); + private static AtomicInteger nextLeafId = new AtomicInteger(); private final InputEdges inputs; private final SuccessorEdges successors; @@ -173,6 +163,8 @@ public final class NodeClass extends FieldIntrospection { private final boolean isSimplifiable; private final boolean isLeafNode; + private final int leafId; + public NodeClass(Class clazz, NodeClass superNodeClass) { this(clazz, superNodeClass, new FieldsScanner.DefaultCalcOffset(), null, 0); } @@ -207,6 +199,11 @@ public final class NodeClass extends FieldIntrospection { } isLeafNode = inputs.getCount() + successors.getCount() == 0; + if (isLeafNode) { + this.leafId = nextLeafId.getAndIncrement(); + } else { + this.leafId = -1; + } canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); startGVNNumber = clazz.getName().hashCode(); @@ -277,16 +274,10 @@ public final class NodeClass extends FieldIntrospection { private final NodeSize size; public NodeCycles cycles() { - if (Options.VerifyNodeCostOnAccess.getValue() && cycles == NodeCycles.CYCLES_UNSET) { - throw new GraalError("Missing NodeCycles specification in the @NodeInfo annotation of the node %s", this); - } return cycles; } public NodeSize size() { - if (Options.VerifyNodeCostOnAccess.getValue() && size == NodeSize.SIZE_UNSET) { - throw new GraalError("Missing NodeSize specification in the @NodeInfo annotation of the node %s", this); - } return size; } @@ -532,7 +523,11 @@ public final class NodeClass extends FieldIntrospection { } private static int deepHashCode0(Object o) { - if (o instanceof Object[]) { + if (o == null) { + return 0; + } else if (!o.getClass().isArray()) { + return o.hashCode(); + } else if (o instanceof Object[]) { return Arrays.deepHashCode((Object[]) o); } else if (o instanceof byte[]) { return Arrays.hashCode((byte[]) o); @@ -550,10 +545,8 @@ public final class NodeClass extends FieldIntrospection { return Arrays.hashCode((double[]) o); } else if (o instanceof boolean[]) { return Arrays.hashCode((boolean[]) o); - } else if (o != null) { - return o.hashCode(); } else { - return 0; + throw shouldNotReachHere(); } } @@ -605,30 +598,47 @@ public final class NodeClass extends FieldIntrospection { } private static boolean deepEquals0(Object e1, Object e2) { - assert e1 != null; - boolean eq; - if (e1 instanceof Object[] && e2 instanceof Object[]) { - eq = Arrays.deepEquals((Object[]) e1, (Object[]) e2); - } else if (e1 instanceof byte[] && e2 instanceof byte[]) { - eq = Arrays.equals((byte[]) e1, (byte[]) e2); - } else if (e1 instanceof short[] && e2 instanceof short[]) { - eq = Arrays.equals((short[]) e1, (short[]) e2); - } else if (e1 instanceof int[] && e2 instanceof int[]) { - eq = Arrays.equals((int[]) e1, (int[]) e2); - } else if (e1 instanceof long[] && e2 instanceof long[]) { - eq = Arrays.equals((long[]) e1, (long[]) e2); - } else if (e1 instanceof char[] && e2 instanceof char[]) { - eq = Arrays.equals((char[]) e1, (char[]) e2); - } else if (e1 instanceof float[] && e2 instanceof float[]) { - eq = Arrays.equals((float[]) e1, (float[]) e2); - } else if (e1 instanceof double[] && e2 instanceof double[]) { - eq = Arrays.equals((double[]) e1, (double[]) e2); - } else if (e1 instanceof boolean[] && e2 instanceof boolean[]) { - eq = Arrays.equals((boolean[]) e1, (boolean[]) e2); + if (e1 == e2) { + return true; + } else if (e1 == null || e2 == null) { + return false; + } else if (!e1.getClass().isArray() || e1.getClass() != e2.getClass()) { + return e1.equals(e2); + } else if (e1 instanceof Object[] && e2 instanceof Object[]) { + return deepEquals((Object[]) e1, (Object[]) e2); + } else if (e1 instanceof int[]) { + return Arrays.equals((int[]) e1, (int[]) e2); + } else if (e1 instanceof long[]) { + return Arrays.equals((long[]) e1, (long[]) e2); + } else if (e1 instanceof byte[]) { + return Arrays.equals((byte[]) e1, (byte[]) e2); + } else if (e1 instanceof char[]) { + return Arrays.equals((char[]) e1, (char[]) e2); + } else if (e1 instanceof short[]) { + return Arrays.equals((short[]) e1, (short[]) e2); + } else if (e1 instanceof float[]) { + return Arrays.equals((float[]) e1, (float[]) e2); + } else if (e1 instanceof double[]) { + return Arrays.equals((double[]) e1, (double[]) e2); + } else if (e1 instanceof boolean[]) { + return Arrays.equals((boolean[]) e1, (boolean[]) e2); } else { - eq = e1.equals(e2); + throw shouldNotReachHere(); } - return eq; + } + + private static boolean deepEquals(Object[] a1, Object[] a2) { + int length = a1.length; + if (a2.length != length) { + return false; + } + + for (int i = 0; i < length; i++) { + if (!deepEquals0(a1[i], a2[i])) { + return false; + } + } + return true; } public boolean dataEquals(Node a, Node b) { @@ -799,10 +809,11 @@ public final class NodeClass extends FieldIntrospection { /** * The template used to build the {@link Verbosity#Name} version. Variable parts are specified - * using {i#inputName} or {p#propertyName}. + * using {i#inputName} or {p#propertyName}. Returns empty string if no + * special name template is specified. */ public String getNameTemplate() { - return nameTemplate.isEmpty() ? shortName() : nameTemplate; + return nameTemplate; } interface InplaceUpdateClosure { @@ -810,15 +821,15 @@ public final class NodeClass extends FieldIntrospection { Node replacement(Node node, Edges.Type type); } - static Map addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable nodes, final DuplicationReplacement replacements) { - final Map newNodes; + static EconomicMap addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable nodes, final DuplicationReplacement replacements) { + final EconomicMap newNodes; int denseThreshold = oldGraph.getNodeCount() + oldGraph.getNodesDeletedSinceLastCompression() >> 4; if (estimatedNodeCount > denseThreshold) { // Use dense map - newNodes = new NodeNodeMap(oldGraph); + newNodes = new NodeMap<>(oldGraph); } else { // Use sparse map - newNodes = newIdentityMap(); + newNodes = EconomicMap.create(Equivalence.IDENTITY); } createNodeDuplicates(graph, nodes, replacements, newNodes); @@ -859,7 +870,7 @@ public final class NodeClass extends FieldIntrospection { return newNodes; } - private static void createNodeDuplicates(final Graph graph, Iterable nodes, final DuplicationReplacement replacements, final Map newNodes) { + private static void createNodeDuplicates(final Graph graph, Iterable nodes, final DuplicationReplacement replacements, final EconomicMap newNodes) { for (Node node : nodes) { if (node != null) { assert !node.isDeleted() : "trying to duplicate deleted node: " + node; @@ -868,15 +879,9 @@ public final class NodeClass extends FieldIntrospection { replacement = replacements.replacement(node); } if (replacement != node) { - if (Fingerprint.ENABLED) { - Fingerprint.submit("replacing %s with %s", node, replacement); - } assert replacement != null; newNodes.put(node, replacement); } else { - if (Fingerprint.ENABLED) { - Fingerprint.submit("duplicating %s", node); - } Node newNode = node.clone(graph, WithAllEdges); assert newNode.getNodeClass().isLeafNode() || newNode.hasNoUsages(); assert newNode.getClass() == node.getClass(); @@ -886,12 +891,12 @@ public final class NodeClass extends FieldIntrospection { } } - private static void transferEdgesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node) { + private static void transferEdgesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final EconomicMap newNodes, Node oldNode, Node node) { transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Inputs); transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Successors); } - private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node, Edges.Type type) { + private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final EconomicMap newNodes, Node oldNode, Node node, Edges.Type type) { NodeClass nodeClass = node.getNodeClass(); NodeClass oldNodeClass = oldNode.getNodeClass(); Edges oldEdges = oldNodeClass.getEdges(type); @@ -926,6 +931,14 @@ public final class NodeClass extends FieldIntrospection { return isLeafNode; } + public int getLeafId() { + return this.leafId; + } + + public NodeClass getSuperNodeClass() { + return superNodeClass; + } + public long inputsIteration() { return inputsIteration; } @@ -1086,6 +1099,25 @@ public final class NodeClass extends FieldIntrospection { return new RawEdgesIterator(node, mask); } } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("succs="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } }; } @@ -1101,6 +1133,25 @@ public final class NodeClass extends FieldIntrospection { return new RawEdgesIterator(node, mask); } } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("inputs="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } }; } @@ -1117,13 +1168,15 @@ public final class NodeClass extends FieldIntrospection { assert other.getNodeClass() == this; while (myMask != 0) { long offset = (myMask & OFFSET_MASK); - Object v1 = UNSAFE.getObject(node, offset); - Object v2 = UNSAFE.getObject(other, offset); if ((myMask & LIST_MASK) == 0) { + Object v1 = Edges.getNodeUnsafe(node, offset); + Object v2 = Edges.getNodeUnsafe(other, offset); if (v1 != v2) { return false; } } else { + Object v1 = Edges.getNodeListUnsafe(node, offset); + Object v2 = Edges.getNodeListUnsafe(other, offset); if (!Objects.equals(v1, v2)) { return false; } @@ -1178,7 +1231,7 @@ public final class NodeClass extends FieldIntrospection { if (curNode != null) { Node newNode = consumer.apply(node, curNode); if (newNode != curNode) { - UNSAFE.putObject(node, offset, newNode); + Edges.putNodeUnsafe(node, offset, newNode); } } } else { @@ -1211,7 +1264,7 @@ public final class NodeClass extends FieldIntrospection { Node curNode = Edges.getNodeUnsafe(node, offset); if (curNode != null) { node.updatePredecessor(curNode, null); - UNSAFE.putObject(node, offset, null); + Edges.putNodeUnsafe(node, offset, null); } } else { unregisterAtSuccessorsAsPredecessorHelper(node, offset); @@ -1276,9 +1329,9 @@ public final class NodeClass extends FieldIntrospection { while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { - Object curNode = UNSAFE.getObject(node, offset); + Object curNode = Edges.getNodeUnsafe(node, offset); if (curNode == key) { - UNSAFE.putObject(node, offset, replacement); + Edges.putNodeUnsafe(node, offset, replacement); return true; } } else { @@ -1333,7 +1386,7 @@ public final class NodeClass extends FieldIntrospection { if (curNode.hasNoUsages()) { node.maybeNotifyZeroUsages(curNode); } - UNSAFE.putObject(node, offset, null); + Edges.putNodeUnsafe(node, offset, null); } } else { unregisterAtInputsAsUsageHelper(node, offset); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java deleted file mode 100644 index 848c9efb041..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.graph; - -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.api.collections.CollectionsProvider; - -/** - * Extends {@link CollectionsProvider} with support for creating {@link Node} based collections. - */ -public interface NodeCollectionsProvider extends CollectionsProvider { - - /** - * Creates a set of {@link Node}s that uses reference-equality in place of object-equality when - * comparing entries. - */ - Set newNodeIdentitySet(); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - */ - Map newNodeIdentityMap(); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - */ - Map newNodeIdentityMap(int expectedMaxSize); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - * - * @param initFrom the returned map is populated with the entries in this map - */ - Map newNodeIdentityMap(Map initFrom); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java index 32ab50d5b65..5b0edb8b39c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.graph; -import java.util.AbstractMap.SimpleEntry; import java.util.Arrays; import java.util.Iterator; -import java.util.Map.Entry; +import java.util.function.BiFunction; -public class NodeMap extends NodeIdAccessor { +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; + +public class NodeMap extends NodeIdAccessor implements EconomicMap { private static final int MIN_REALLOC_SIZE = 16; @@ -43,6 +45,7 @@ public class NodeMap extends NodeIdAccessor { this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length); } + @Override @SuppressWarnings("unchecked") public T get(Node node) { assert check(node); @@ -62,16 +65,15 @@ public class NodeMap extends NodeIdAccessor { assert check(node); } + @Override public boolean isEmpty() { - return !entries().iterator().hasNext(); + throw new UnsupportedOperationException("isEmpty() is not supported for performance reasons"); } - public boolean containsKey(Object key) { - if (key instanceof Node) { - Node node = (Node) key; - if (node.graph() == graph()) { - return get(node) != null; - } + @Override + public boolean containsKey(Node node) { + if (node.graph() == graph()) { + return get(node) != null; } return false; } @@ -96,7 +98,7 @@ public class NodeMap extends NodeIdAccessor { public void setAndGrow(Node node, T value) { checkAndGrow(node); - values[getNodeId(node)] = value; + set(node, value); } /** @@ -107,12 +109,17 @@ public class NodeMap extends NodeIdAccessor { return graph.getNode(i); } + @Override public int size() { + throw new UnsupportedOperationException("size() is not supported for performance reasons"); + } + + public int capacity() { return values.length; } public boolean isNew(Node node) { - return getNodeId(node) >= size(); + return getNodeId(node) >= capacity(); } private boolean check(Node node) { @@ -121,16 +128,92 @@ public class NodeMap extends NodeIdAccessor { return true; } + @Override public void clear() { Arrays.fill(values, null); } - public Iterable> entries() { - return new Iterable>() { + @Override + public Iterable getKeys() { + return new Iterable() { @Override - public Iterator> iterator() { - return new Iterator>() { + public Iterator iterator() { + return new Iterator() { + + int i = 0; + + @Override + public boolean hasNext() { + forward(); + return i < NodeMap.this.values.length; + } + + @Override + public Node next() { + final int pos = i; + final Node key = NodeMap.this.getKey(pos); + i++; + forward(); + return key; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + private void forward() { + while (i < NodeMap.this.values.length && (NodeMap.this.getKey(i) == null || NodeMap.this.values[i] == null)) { + i++; + } + } + }; + } + }; + } + + @Override + public MapCursor getEntries() { + return new MapCursor() { + + int current = -1; + + @Override + public boolean advance() { + current++; + while (current < NodeMap.this.values.length && (NodeMap.this.values[current] == null || NodeMap.this.getKey(current) == null)) { + current++; + } + return current < NodeMap.this.values.length; + } + + @Override + public Node getKey() { + return NodeMap.this.getKey(current); + } + + @SuppressWarnings("unchecked") + @Override + public T getValue() { + return (T) NodeMap.this.values[current]; + } + + @Override + public void remove() { + assert NodeMap.this.values[current] != null; + NodeMap.this.values[current] = null; + } + }; + } + + @Override + public Iterable getValues() { + return new Iterable() { + + @Override + public Iterator iterator() { + return new Iterator() { int i = 0; @@ -142,23 +225,12 @@ public class NodeMap extends NodeIdAccessor { @SuppressWarnings("unchecked") @Override - public Entry next() { + public T next() { final int pos = i; - Node key = NodeMap.this.getKey(pos); - T value = (T) NodeMap.this.values[pos]; + final T value = (T) NodeMap.this.values[pos]; i++; forward(); - return new SimpleEntry(key, value) { - - private static final long serialVersionUID = 7813842391085737738L; - - @Override - public T setValue(T v) { - T oldv = super.setValue(v); - NodeMap.this.values[pos] = v; - return oldv; - } - }; + return value; } @Override @@ -178,24 +250,42 @@ public class NodeMap extends NodeIdAccessor { @Override public String toString() { - Iterator> i = entries().iterator(); - if (!i.hasNext()) { + MapCursor i = getEntries(); + if (!i.advance()) { return "{}"; } StringBuilder sb = new StringBuilder(); sb.append('{'); while (true) { - Entry e = i.next(); - Node key = e.getKey(); - T value = e.getValue(); + Node key = i.getKey(); + T value = i.getValue(); sb.append(key); sb.append('='); sb.append(value); - if (!i.hasNext()) { + if (!i.advance()) { return sb.append('}').toString(); } sb.append(',').append(' '); } } + + @Override + public T put(Node key, T value) { + T result = get(key); + set(key, value); + return result; + } + + @Override + public T removeKey(Node key) { + return put(key, null); + } + + @Override + public void replaceAll(BiFunction function) { + for (Node n : getKeys()) { + put(n, function.apply(n, get(n))); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java deleted file mode 100644 index 31e4071d688..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.graph; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public final class NodeNodeMap extends NodeMap implements Map { - - public NodeNodeMap(Graph graph) { - super(graph); - } - - public NodeNodeMap(NodeNodeMap copyFrom) { - super(copyFrom); - } - - @Override - public Node get(Object key) { - return super.get((Node) key); - } - - @Override - public Node put(Node key, Node value) { - Node oldValue = super.get(key); - super.set(key, value); - return oldValue; - } - - @Override - public Node remove(Object key) { - throw new UnsupportedOperationException("Cannot remove keys from this map"); - } - - @Override - public void putAll(Map m) { - for (Entry entry : m.entrySet()) { - put(entry.getKey(), entry.getValue()); - } - } - - @Override - public Set keySet() { - HashSet entries = new HashSet<>(); - for (int i = 0; i < values.length; ++i) { - Object v = values[i]; - if (v != null) { - Node key = getKey(i); - if (key != null) { - entries.add(key); - } - } - } - /* - * The normal contract for entrySet is that modifications of the set are reflected in the - * underlying data structure. For simplicity don't allow that but complain if someone tries - * to use it that way. - */ - return Collections.unmodifiableSet(entries); - } - - @Override - public Collection values() { - ArrayList result = new ArrayList<>(this.size()); - for (int i = 0; i < values.length; ++i) { - Object v = values[i]; - if (v != null) { - result.add((Node) v); - } - } - return result; - } - - @Override - public Set> entrySet() { - HashSet> entries = new HashSet<>(); - for (Map.Entry entry : entries()) { - entries.add(entry); - } - /* - * The normal contract for entrySet is that modifications of the set are reflected in the - * underlying data structure. For simplicity don't allow that but complain if someone tries - * to use it that way. - */ - return Collections.unmodifiableSet(entries); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java index f747d79a40e..688eb793968 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java @@ -36,9 +36,15 @@ public class NodeSourcePosition extends BytecodePosition { * The receiver of the method this frame refers to. */ private final JavaConstant receiver; + private final int hashCode; public NodeSourcePosition(JavaConstant receiver, NodeSourcePosition caller, ResolvedJavaMethod method, int bci) { super(caller, method, bci); + if (caller == null) { + this.hashCode = 31 * bci + method.hashCode(); + } else { + this.hashCode = caller.hashCode * 7 + 31 * bci + method.hashCode(); + } this.receiver = receiver; assert receiver == null || method.getDeclaringClass().isInstance(receiver); } @@ -50,6 +56,9 @@ public class NodeSourcePosition extends BytecodePosition { } if (obj != null && getClass() == obj.getClass()) { NodeSourcePosition that = (NodeSourcePosition) obj; + if (hashCode != that.hashCode) { + return false; + } if (this.getBCI() == that.getBCI() && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.getCaller(), that.getCaller()) && Objects.equals(this.receiver, that.receiver)) { return true; @@ -58,6 +67,11 @@ public class NodeSourcePosition extends BytecodePosition { return false; } + @Override + public int hashCode() { + return hashCode; + } + public JavaConstant getReceiver() { return receiver; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java index 5e82577feaa..754e50e90b6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,14 +23,21 @@ package org.graalvm.compiler.graph; public final class NodeStack { - - private static final int INITIAL_SIZE = 8; + private static final int DEFAULT_INITIAL_SIZE = 8; protected Node[] values; public int tos; public NodeStack() { - values = new Node[INITIAL_SIZE]; + this(DEFAULT_INITIAL_SIZE); + } + + public NodeStack(int initialSize) { + values = new Node[initialSize]; + } + + public int size() { + return tos; } public void push(Node n) { @@ -49,6 +56,10 @@ public final class NodeStack { values = newValues; } + public Node get(int index) { + return values[index]; + } + public Node pop() { assert tos > 0 : "stack must be non-empty"; return values[--tos]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java index b84fadadbf4..37f7a76629b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java @@ -24,6 +24,8 @@ package org.graalvm.compiler.graph; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; +import java.util.Iterator; + import org.graalvm.compiler.graph.iterators.NodeIterable; class NodeUsageIterable implements NodeIterable { @@ -62,4 +64,23 @@ class NodeUsageIterable implements NodeIterable { public int count() { return node.getUsageCount(); } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("usages="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java index 335826d2cdf..4289c9fae90 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java @@ -27,6 +27,8 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; +import org.graalvm.compiler.debug.Debug; + public abstract class NodeWorkList implements Iterable { protected final Queue worklist; @@ -70,20 +72,19 @@ public abstract class NodeWorkList implements Iterable { } public static final class IterativeNodeWorkList extends NodeWorkList { - private static final int EXPLICIT_BITMAP_THRESHOLD = 10; protected NodeBitMap inQueue; - private int iterationLimit = Integer.MAX_VALUE; + private int iterationLimit; private Node firstNoChange; private Node lastPull; private Node lastChain; public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { super(graph, fill); - if (iterationLimitPerNode > 0) { - iterationLimit = iterationLimitPerNode * graph.getNodeCount(); - } + assert iterationLimitPerNode > 0; + long limit = (long) iterationLimitPerNode * graph.getNodeCount(); + iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit); } @Override @@ -92,7 +93,11 @@ public abstract class NodeWorkList implements Iterable { @Override public boolean hasNext() { dropDeleted(); - return iterationLimit > 0 && !worklist.isEmpty(); + if (iterationLimit <= 0) { + Debug.log(Debug.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList"); + return false; + } + return !worklist.isEmpty(); } @Override @@ -137,7 +142,7 @@ public abstract class NodeWorkList implements Iterable { } } } - assert checkInfiniteWork(node) : "Readded " + node; + assert checkInfiniteWork(node) : "Re-added " + node; if (inQueue != null) { inQueue.markAndGrow(node); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java index e018065bbbe..a879bbe978b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.graph; -import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; @@ -40,7 +39,6 @@ class TypedGraphNodeIterator implements Iterator ids = clazz.iterableIds(); currentIdIndex = 0; current = new Node[ids.length]; - Arrays.fill(current, Graph.PLACE_HOLDER); needsForward = true; } @@ -67,7 +65,7 @@ class TypedGraphNodeIterator implements Iterator int startIdx = currentIdIndex; while (true) { Node next; - if (current() == Graph.PLACE_HOLDER) { + if (current() == null) { next = graph.getIterableNodeStart(ids[currentIdIndex]); } else { next = graph.getIterableNodeNext(current().typeCacheNext); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java index 84ace707a11..267497669d6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java @@ -22,13 +22,20 @@ */ package org.graalvm.compiler.graph.iterators; +import java.util.function.Predicate; + import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodePredicates.AndPredicate; -public interface NodePredicate { +public interface NodePredicate extends Predicate { boolean apply(Node n); + @Override + default boolean test(Node n) { + return apply(n); + } + default NodePredicate and(NodePredicate np) { return new AndPredicate(this, np); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java index f52306dd68f..a467a742e12 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java @@ -105,6 +105,7 @@ public abstract class NodePredicates { return !a.apply(n); } + @Override public NodePredicate negate() { return a; } @@ -148,6 +149,7 @@ public abstract class NodePredicates { return this; } + @Override public NodePredicate negate() { return new NegativeTypePredicate(this); } @@ -183,6 +185,7 @@ public abstract class NodePredicates { return this; } + @Override public NodePredicate negate() { return new PositiveTypePredicate(this); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java index e7fc59fe646..c952b746bc2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java @@ -28,6 +28,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.options.OptionValues; public interface CanonicalizerTool { @@ -49,8 +50,10 @@ public interface CanonicalizerTool { boolean allUsagesAvailable(); /** - * Indicates whether the target platform supports comparison of integers of a particular bit - * width. This check is used by canonicalizations that might introduce subword compares. + * Indicates the smallest width for comparing an integer value on the target platform. If this + * method returns null, then there is no known smallest compare width. */ - boolean supportSubwordCompare(int bits); + Integer smallestCompareWidth(); + + OptionValues getOptions(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index 8d3b056e404..ba1623af90a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -31,8 +31,6 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; -import java.util.Set; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; @@ -66,6 +64,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.spi.NodeLIRBuilderTool; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -140,35 +139,39 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } crb.blockComment("[method prologue]"); - if (ZapStackOnMethodEntry.getValue()) { - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - int intSize = 4; - AArch64Address address = AArch64Address.createPreIndexedImmediateAddress(scratch, -intSize); - try (ScratchRegister sc2 = masm.getScratchRegister()) { - Register value = sc2.getRegister(); - masm.mov(value, 0xC1C1C1C1); - for (int i = 0; i < frameSize; i += intSize) { - masm.str(32, value, address); - } - } - masm.mov(64, sp, scratch); - } - } else { - if (AArch64MacroAssembler.isArithmeticImmediate(totalFrameSize)) { + try (ScratchRegister sc = masm.getScratchRegister()) { + int wordSize = crb.target.arch.getWordSize(); + Register rscratch1 = sc.getRegister(); + assert totalFrameSize > 0; + if (frameSize < 1 << 9) { masm.sub(64, sp, sp, totalFrameSize); + masm.stp(64, fp, lr, AArch64Address.createScaledImmediateAddress(sp, frameSize / wordSize)); } else { - try (ScratchRegister sc2 = masm.getScratchRegister()) { - Register scratch2 = sc2.getRegister(); - masm.mov(scratch2, totalFrameSize); - masm.sub(64, sp, sp, scratch2); + masm.stp(64, fp, lr, AArch64Address.createPreIndexedImmediateAddress(sp, -2)); + if (frameSize < 1 << 12) { + masm.sub(64, sp, sp, totalFrameSize - 2 * wordSize); + } else { + masm.mov(rscratch1, totalFrameSize - 2 * wordSize); + masm.sub(64, sp, sp, rscratch1); } } } + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { + try (ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + int longSize = 8; + masm.mov(64, scratch, sp); + AArch64Address address = AArch64Address.createPostIndexedImmediateAddress(scratch, longSize); + try (ScratchRegister sc2 = masm.getScratchRegister()) { + Register value = sc2.getRegister(); + masm.mov(value, 0xBADDECAFFC0FFEEL); + for (int i = 0; i < frameSize; i += longSize) { + masm.str(64, value, address); + } + } - AArch64Address address2 = AArch64Address.createPairUnscaledImmediateAddress(sp, frameSize / 8); // XXX - masm.stp(64, fp, lr, address2); - + } + } crb.blockComment("[code body]"); } @@ -176,23 +179,28 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { public void leave(CompilationResultBuilder crb) { AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; - final int frameSize = frameMap.frameSize(); final int totalFrameSize = frameMap.totalFrameSize(); crb.blockComment("[method epilogue]"); - - AArch64Address address2 = AArch64Address.createPairUnscaledImmediateAddress(sp, frameSize / 8); // XXX - masm.ldp(64, fp, lr, address2); - - if (AArch64MacroAssembler.isArithmeticImmediate(totalFrameSize)) { - masm.add(64, sp, sp, totalFrameSize); - } else { - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - masm.mov(scratch, totalFrameSize); - masm.add(64, sp, sp, scratch); + try (ScratchRegister sc = masm.getScratchRegister()) { + int wordSize = crb.target.arch.getWordSize(); + Register rscratch1 = sc.getRegister(); + final int frameSize = frameMap.frameSize(); + assert totalFrameSize > 0; + if (frameSize < 1 << 9) { + masm.ldp(64, fp, lr, AArch64Address.createScaledImmediateAddress(sp, frameSize / wordSize)); + masm.add(64, sp, sp, totalFrameSize); + } else { + if (frameSize < 1 << 12) { + masm.add(64, sp, sp, totalFrameSize - 2 * wordSize); + } else { + masm.mov(rscratch1, totalFrameSize - 2 * wordSize); + masm.add(64, sp, sp, rscratch1); + } + masm.ldp(64, fp, lr, AArch64Address.createPostIndexedImmediateAddress(sp, 2)); } } + } @Override @@ -218,7 +226,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -227,7 +235,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } if (stub != null) { - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); } return crb; @@ -315,13 +323,13 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AArch64HotSpotRegisterAllocationConfig(registerConfigNonNull); + return new AArch64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { return calleeRegisters; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java index 64d47cb243d..1b8d7061a80 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java @@ -27,8 +27,9 @@ import static jdk.vm.ci.common.InitTimer.timer; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.core.aarch64.AArch64AddressLowering; -import org.graalvm.compiler.core.aarch64.AArch64SuitesProvider; +import org.graalvm.compiler.core.aarch64.AArch64AddressLoweringByUse; +import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; +import org.graalvm.compiler.core.aarch64.AArch64SuitesCreator; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotBackendFactory; @@ -46,10 +47,9 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins; @@ -106,7 +106,6 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { HotSpotSuitesProvider suites; HotSpotWordTypes wordTypes; Plugins plugins; - NodeCostProvider nodeCostProvider; BytecodeProvider bytecodeProvider; try (InitTimer t = timer("create providers")) { try (InitTimer rt = timer("create HotSpotRegisters provider")) { @@ -124,11 +123,8 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { try (InitTimer rt = timer("create Lowerer provider")) { lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, target); } - try (InitTimer rt = timer("create NodeCost provider")) { - nodeCostProvider = createNodeCostProvider(); - } HotSpotStampProvider stampProvider = new HotSpotStampProvider(); - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, nodeCostProvider); + Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider); try (InitTimer rt = timer("create SnippetReflection provider")) { snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes); @@ -137,16 +133,16 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(p, snippetReflection, bytecodeProvider); + replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { suites = createSuites(config, graalRuntime, compilerConfiguration, plugins); } - providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, nodeCostProvider, suites, registers, + providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); } @@ -155,11 +151,11 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { } } - protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, - HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, - HotSpotStampProvider stampProvider) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - AArch64GraphBuilderPlugins.register(plugins, foreignCalls, replacements.getReplacementBytecodeProvider()); + protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection, + HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, + HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider()); return plugins; } @@ -171,8 +167,8 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(AArch64HotSpotRegisterConfig.threadRegister, AArch64HotSpotRegisterConfig.heapBaseRegister, sp); } - protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, @@ -181,7 +177,7 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { } protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins) { - return new HotSpotSuitesProvider(new AArch64SuitesProvider(compilerConfiguration, plugins), config, runtime, new AArch64AddressLowering()); + return new AArch64HotSpotSuitesProvider(new AArch64SuitesCreator(compilerConfiguration, plugins), config, runtime, new AArch64AddressLoweringByUse(new AArch64LIRKindTool())); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { @@ -193,10 +189,6 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { return new AArch64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, target); } - protected HotSpotNodeCostProvider createNodeCostProvider() { - return new AArchHotSpotNodeCostProvider(); - } - protected static Value[] createNativeABICallerSaveRegisters(@SuppressWarnings("unused") GraalHotSpotVMConfig config, RegisterConfig regConfig) { AArch64HotSpotRegisterConfig conf = (AArch64HotSpotRegisterConfig) regConfig; RegisterArray callerSavedRegisters = conf.getCallerSaveRegisters(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java index d7aefd8293d..054fb34bda9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.hotspot.aarch64; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.aarch64.AArch64.r0; import static jdk.vm.ci.aarch64.AArch64.r3; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; +import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -63,7 +62,7 @@ public class AArch64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsP } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -76,16 +75,12 @@ public class AArch64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsP register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - throw GraalError.unimplemented("PreferGraalStubs"); - } - // These stubs do callee saving if (config.useCRC32Intrinsics) { registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java index 52fbb28d51a..f2eb47b145a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java @@ -68,16 +68,19 @@ public class AArch64HotSpotJumpToExceptionHandlerInCallerOp extends AArch64HotSp public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { leaveFrame(crb, masm, /* emitSafepoint */false); - // 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); - masm.ldr(32, scratch, address); - Label noRestore = new Label(); - masm.cbz(32, scratch, noRestore); - masm.mov(64, sp, fp); - masm.bind(noRestore); + if (System.getProperty("java.specification.version").compareTo("1.8") < 0) { + // 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); + masm.ldr(32, scratch, address); + Label noRestore = new Label(); + masm.cbz(32, scratch, noRestore); + masm.mov(64, sp, fp); + masm.bind(noRestore); + } } + masm.jmp(asRegister(handlerInCallerPc)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java index d8b03b30c85..b5939674dd9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java @@ -29,24 +29,24 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import java.util.function.Function; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator; import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; +import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -58,9 +58,11 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; +import org.graalvm.compiler.lir.aarch64.AArch64CCall; import org.graalvm.compiler.lir.aarch64.AArch64Call; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64FrameMapBuilder; +import org.graalvm.compiler.lir.aarch64.AArch64Move; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -91,7 +93,7 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H private HotSpotDebugInfoBuilder debugInfoBuilder; protected AArch64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { - this(new AArch64HotSpotLIRKindTool(), new AArch64ArithmeticLIRGenerator(), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); + this(new AArch64LIRKindTool(), new AArch64ArithmeticLIRGenerator(), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); } protected AArch64HotSpotLIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, @@ -129,6 +131,19 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H } @Override + public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args) { + Value[] argLocations = new Value[args.length]; + getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention); + for (int i = 0; i < args.length; i++) { + Value arg = args[i]; + AllocatableValue loc = nativeCallingConvention.getArgument(i); + emitMove(loc, arg); + argLocations[i] = loc; + } + Value ptr = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(address)); + append(new AArch64CCall(nativeCallingConvention.getReturn(), ptr, argLocations)); + } + public SaveRegistersOp emitSaveAllRegisters() { throw GraalError.unimplemented(); } @@ -193,8 +208,8 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -214,14 +229,25 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; } } + @Override + public void emitNullCheck(Value address, LIRFrameState state) { + if (address.getValueKind().getPlatformKind() == AArch64Kind.DWORD) { + CompressEncoding encoding = config.getOopEncoding(); + Value uncompressed = emitUncompress(address, encoding, false); + append(new AArch64Move.NullCheckOp(asAddressValue(uncompressed), state)); + } else { + super.emitNullCheck(address, state); + } + } + @Override public void emitPrefetchAllocate(Value address) { append(new AArch64PrefetchOp(asAddressValue(address), config.allocatePrefetchInstr)); @@ -294,8 +320,7 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H LIRKind wordKind = LIRKind.value(target().arch.getWordKind()); RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind); final int transferSize = value.getValueKind().getPlatformKind().getSizeInBytes(); - final int scaledDisplacement = offset >> NumUtil.log2Ceil(transferSize); - AArch64AddressValue address = new AArch64AddressValue(value.getValueKind(), thread, Value.ILLEGAL, scaledDisplacement, true, AddressingMode.IMMEDIATE_SCALED); + AArch64AddressValue address = new AArch64AddressValue(value.getValueKind(), thread, Value.ILLEGAL, offset, transferSize, AddressingMode.IMMEDIATE_SCALED); append(new StoreOp((AArch64Kind) value.getPlatformKind(), address, loadReg(value), null)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java index 8aa3a0483dc..63e7c07ce93 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.nodes.calc.FixedBinaryNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.calc.RemNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.aarch64.AArch64FloatArithmeticSnippets; import org.graalvm.compiler.replacements.aarch64.AArch64IntegerArithmeticSnippets; @@ -52,10 +53,10 @@ public class AArch64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvid } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - super.initialize(providers, config); + public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { + integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + super.initialize(options, providers, config); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java index 89dc03de43e..b0de7d96da3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java @@ -22,16 +22,18 @@ */ package org.graalvm.compiler.hotspot.aarch64; +import static jdk.vm.ci.aarch64.AArch64.zr; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; -import 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.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; @@ -61,7 +63,7 @@ public class AArch64HotSpotMove { crb.recordInlineDataInCode(constant); if (constant.isCompressed()) { // masm.forceMov(asRegister(result), 0); - throw GraalError.unimplemented(); + masm.movNarrowAddress(asRegister(result), 0); } else { masm.movNativeAddress(asRegister(result), 0); } @@ -104,29 +106,26 @@ public class AArch64HotSpotMove { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register resultRegister = asRegister(result); Register ptr = asRegister(input); - Register base = asRegister(baseRegister); + Register base = (isRegister(baseRegister) ? asRegister(baseRegister) : zr); // result = (ptr - base) >> shift - if (encoding.base == 0) { - if (encoding.shift == 0) { - masm.movx(resultRegister, ptr); + if (!encoding.hasBase()) { + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, ptr, encoding.getShift()); } else { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.lshr(64, resultRegister, ptr, encoding.shift); + masm.movx(resultRegister, ptr); } } else if (nonNull) { masm.sub(64, resultRegister, ptr, base); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.shl(64, resultRegister, resultRegister, encoding.shift); + if (encoding.hasShift()) { + masm.shl(64, resultRegister, resultRegister, encoding.getShift()); } } else { // if ptr is null it still has to be null after compression masm.cmp(64, ptr, 0); masm.cmov(64, resultRegister, ptr, base, AArch64Assembler.ConditionFlag.NE); masm.sub(64, resultRegister, resultRegister, base); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.lshr(64, resultRegister, resultRegister, encoding.shift); + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, resultRegister, encoding.getShift()); } } } @@ -158,17 +157,22 @@ public class AArch64HotSpotMove { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register ptr = asRegister(input); Register resultRegister = asRegister(result); - Register base = asRegister(baseRegister); + Register base = (isRegister(baseRegister) ? asRegister(baseRegister) : zr); // result = base + (ptr << shift) if (nonNull) { - assert encoding.shift == encoding.alignment; - masm.add(64, resultRegister, base, ptr, AArch64Assembler.ShiftType.ASR, encoding.shift); + masm.add(64, resultRegister, base, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + } else if (!encoding.hasBase()) { + masm.add(64, resultRegister, zr, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift()); } else { // if ptr is null it has to be null after decompression - // masm.cmp(64, ); - throw GraalError.unimplemented(); + Label done = new Label(); + if (!resultRegister.equals(ptr)) { + masm.mov(32, resultRegister, ptr); + } + masm.cbz(32, resultRegister, done); + masm.add(64, resultRegister, base, resultRegister, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + masm.bind(done); } - } } @@ -188,10 +192,8 @@ public class AArch64HotSpotMove { public static void decodeKlassPointer(AArch64MacroAssembler masm, Register result, Register ptr, Register klassBase, CompressEncoding encoding) { // result = klassBase + ptr << shift - if (encoding.shift != 0 || encoding.base != 0) { - // (shift != 0 -> shift == alignment) - assert (encoding.shift == 0 || encoding.shift == encoding.alignment) : "Decode algorithm is wrong: " + encoding; - masm.add(64, result, klassBase, ptr, AArch64Assembler.ExtendType.UXTX, encoding.shift); + if (encoding.hasShift() || encoding.hasBase()) { + masm.add(64, result, klassBase, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java index 641cf5d8bd3..162de6d0f33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java @@ -31,18 +31,18 @@ import org.graalvm.compiler.lir.LIRInstruction; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; public class AArch64HotSpotMoveFactory extends AArch64MoveFactory { @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; - } else if (c instanceof HotSpotObjectConstant) { + } else if (c instanceof HotSpotObjectConstant || c instanceof HotSpotMetaspaceConstant) { return false; } else { return super.canInlineConstant(c); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java index 1352a913af2..d3d770d9e00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java @@ -39,13 +39,11 @@ import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.aarch64.AArch64BreakpointOp; -import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -70,7 +68,6 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.Value; -import jdk.vm.ci.meta.ValueKind; /** * LIR generator specialized for AArch64 HotSpot. @@ -180,20 +177,6 @@ public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implemen } } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); - AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); - AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); - ValueKind kind = cmpValue.getValueKind(); - assert kind.equals(newValue.getValueKind()); - - Variable result = gen.newVariable(newValue.getValueKind()); - Variable scratch = gen.newVariable(LIRKind.value(AArch64Kind.DWORD)); - append(new CompareAndSwapOp(result, cmpValue, newValue, address, scratch)); - setResult(x, result); - } - @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java index 5848b3bdda9..15e4e38ff8f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java @@ -28,7 +28,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AArch64ExceptionCode; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; @@ -54,9 +53,9 @@ final class AArch64HotSpotPatchReturnAddressOp extends AArch64LIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { final int frameSize = crb.frameMap.frameSize(); - // XXX where is lr exactly? - AArch64Address lrAddress = AArch64Address.createUnscaledImmediateAddress(sp, frameSize); - masm.brk(AArch64ExceptionCode.BREAKPOINT); // XXX + // LR is saved in the {fp, lr} pair above the frame + AArch64Address lrAddress = AArch64Address.createUnscaledImmediateAddress(sp, + frameSize + crb.target.wordSize); masm.str(64, asRegister(address), lrAddress); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java index ac9b0967dc5..d4013c5974e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java @@ -109,8 +109,8 @@ public class AArch64HotSpotRegisterAllocationConfig extends RegisterAllocationCo }; // @formatter:on - public AArch64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + public AArch64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java index 02b2146c36a..a2023faf776 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot.aarch64; import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -77,18 +77,18 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction { } public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register scratch, LIRFrameState state) { - int pos = masm.position(); if (isPollingPageFar(config)) { crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); masm.movNativeAddress(scratch, config.safepointPollingAddress); + crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); } masm.ldr(32, zr, AArch64Address.createBaseRegisterOnlyAddress(scratch)); } else { crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_NEAR : config.MARKID_POLL_NEAR); if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); } masm.ldr(32, zr, AArch64Address.createPcLiteralAddress(0)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java new file mode 100644 index 00000000000..5215f79fc9f --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java @@ -0,0 +1,65 @@ +/* + * 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.tiers.LowTierContext; +import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.phases.tiers.SuitesCreator; + +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> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class); + if (findPhase == null) { + findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class); + } + findPhase.add(new AddressLoweringByUsePhase(addressLoweringByUse)); + + return suites; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java new file mode 100644 index 00000000000..1bd87780929 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; + +import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder; +import org.graalvm.compiler.core.common.type.RawPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.hotspot.HotSpotCallingConventionType; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Value; + +@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_UNKNOWN) +public final class AArch64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AArch64RawNativeCallNode.class); + + protected final JavaConstant functionPointer; + @Input NodeInputList args; + + public AArch64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) { + super(TYPE, StampFactory.forKind(returnType)); + this.functionPointer = functionPointer; + this.args = new NodeInputList<>(this, args); + } + + private static class PointerType implements JavaType { + + @Override + public String getName() { + return "void*"; + } + + @Override + public JavaType getComponentType() { + return null; + } + + @Override + public JavaType getArrayClass() { + return null; + } + + @Override + public JavaKind getJavaKind() { + // native pointers and java objects use the same registers in the calling convention + return JavaKind.Object; + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return null; + } + } + + private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) { + if (stamp instanceof RawPointerStamp) { + return new PointerType(); + } else { + return stamp.javaType(metaAccess); + } + } + + @Override + public void generate(NodeLIRBuilderTool generator) { + AArch64NodeLIRBuilder gen = (AArch64NodeLIRBuilder) generator; + Value[] parameter = new Value[args.count()]; + JavaType[] parameterTypes = new JavaType[args.count()]; + for (int i = 0; i < args.count(); i++) { + parameter[i] = generator.operand(args.get(i)); + parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess()); + } + JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess()); + CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes, + generator.getLIRGeneratorTool()); + gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter); + if (this.getStackKind() != JavaKind.Void) { + generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn())); + } + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java index 31b67987d9e..706b1fd36d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java @@ -22,19 +22,13 @@ */ package org.graalvm.compiler.hotspot.amd64.test; -import org.junit.Assert; +import static org.graalvm.compiler.core.common.GraalOptions.OptImplicitNullChecks; + +import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; +import org.graalvm.compiler.options.OptionValues; import org.junit.Assume; import org.junit.Test; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.IsNullNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -57,16 +51,15 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { Container c = new Container(); c.i = i; - try (OverrideScope s = OptionValue.override(GraalOptions.OptImplicitNullChecks, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("testSnippet"); - Result expect = executeExpected(method, null, c); + ResolvedJavaMethod method = getResolvedJavaMethod("testSnippet"); + Result expect = executeExpected(method, null, c); - // make sure we don't get a profile that removes the implicit null check - method.reprofile(); + // make sure we don't get a profile that removes the implicit null check + method.reprofile(); - Result actual = executeActual(method, null, c); - assertEquals(expect, actual); - } + OptionValues options = new OptionValues(getInitialOptions(), OptImplicitNullChecks, true); + Result actual = executeActual(options, method, null, c); + assertEquals(expect, actual); } @SuppressWarnings("try") @@ -76,9 +69,7 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { Container c = new Container(); c.i = i; - try (OverrideScope s = OptionValue.override(GraalOptions.OptImplicitNullChecks, false)) { - test("testSnippet", c); - } + test(new OptionValues(getInitialOptions(), OptImplicitNullChecks, false), "testSnippet", c); } @Test @@ -100,18 +91,4 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { public void explicitNull() { testExplicit(null); } - - @Override - protected boolean checkMidTierGraph(StructuredGraph graph) { - int count = 0; - for (IsNullNode isNull : graph.getNodes().filter(IsNullNode.class).snapshot()) { - ValueNode value = isNull.getValue(); - if (value instanceof CompressionNode) { - count++; - isNull.replaceFirstInput(value, ((CompressionNode) value).getValue()); - } - } - Assert.assertEquals("graph should contain exactly one IsNullNode", 1, count); - return super.checkMidTierGraph(graph); - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java index 3c83cc47b11..4d1adff918e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java @@ -23,20 +23,15 @@ package org.graalvm.compiler.hotspot.amd64.test; +import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import static jdk.vm.ci.code.ValueUtil.asRegister; - -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; @@ -46,12 +41,16 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.nodes.type.NarrowOopStamp; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.meta.AllocatableValue; @@ -141,9 +140,8 @@ public class DataPatchInConstantsTest extends HotSpotGraalCompilerTest { } @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - Registration r = new Registration(plugins.getInvocationPlugins(), DataPatchInConstantsTest.class); + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { + Registration r = new Registration(invocationPlugins, DataPatchInConstantsTest.class); r.register1("loadThroughPatch", Object.class, new InvocationPlugin() { @Override @@ -156,14 +154,13 @@ public class DataPatchInConstantsTest extends HotSpotGraalCompilerTest { r.register1("loadThroughCompressedPatch", Object.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - ValueNode compressed = b.add(CompressionNode.compress(arg, runtime().getVMConfig().getOopEncoding())); + ValueNode compressed = b.add(HotSpotCompressionNode.compress(arg, runtime().getVMConfig().getOopEncoding())); ValueNode patch = b.add(new LoadThroughPatchNode(compressed)); - b.addPush(JavaKind.Object, CompressionNode.uncompress(patch, runtime().getVMConfig().getOopEncoding())); + b.addPush(JavaKind.Object, HotSpotCompressionNode.uncompress(patch, runtime().getVMConfig().getOopEncoding())); return true; } }); - - return plugins; + super.registerInvocationPlugins(invocationPlugins); } @NodeInfo(cycles = CYCLES_2, size = SIZE_1) diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java index b7b473b8b47..b72925f67eb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java @@ -25,13 +25,10 @@ package org.graalvm.compiler.hotspot.amd64.test; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.DataPointerConstant; @@ -52,6 +49,12 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64.CPUFeature; @@ -59,6 +62,7 @@ import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.ValueUtil; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; @@ -163,13 +167,20 @@ public class StubAVXTest extends LIRTest { private static class TestStub extends SnippetStub { - TestStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("testStub", providers, linkage); + TestStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("testStub", options, providers, linkage); } @Snippet static void testStub() { } + + @Override + protected BytecodeProvider getReplacementsBytecodeProvider() { + ReplacementsImpl d = (ReplacementsImpl) providers.getReplacements(); + MetaAccessProvider metaAccess = d.providers.getMetaAccess(); + return new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader()); + } } public static final ForeignCallDescriptor TEST_STUB = new ForeignCallDescriptor("test_stub", void.class); @@ -208,7 +219,7 @@ public class StubAVXTest extends LIRTest { HotSpotProviders providers = (HotSpotProviders) getProviders(); HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls(); HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, true, HotSpotForeignCallLinkage.Transition.LEAF_NOFP); - linkage.setCompiledStub(new TestStub(providers, linkage)); + linkage.setCompiledStub(new TestStub(getInitialOptions(), providers, linkage)); runTest("testStub"); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java deleted file mode 100644 index d0d77efd99b..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.amd64; - -import static jdk.vm.ci.amd64.AMD64.r10; -import static jdk.vm.ci.amd64.AMD64.r11; -import static jdk.vm.ci.amd64.AMD64.r13; -import static jdk.vm.ci.amd64.AMD64.r14; -import static jdk.vm.ci.amd64.AMD64.r8; -import static jdk.vm.ci.amd64.AMD64.r9; -import static jdk.vm.ci.amd64.AMD64.rbx; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdi; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.rsi; - -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; - -final class AMD64DeoptimizationStub extends DeoptimizationStub { - - private RegisterConfig registerConfig; - - AMD64DeoptimizationStub(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - registerConfig = new AMD64HotSpotRegisterConfig(target, new RegisterArray(rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14), config.windowsOs); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java index d8c5cd6227a..4ace1afac75 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -27,34 +27,40 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64AddressLowering; import org.graalvm.compiler.core.amd64.AMD64AddressNode; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.CompressionNode.CompressionOp; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.CompressionNode; +import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.JavaKind; public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { + private static final DebugCounter counterFoldedUncompressDuringAddressLowering = Debug.counter("FoldedUncompressDuringAddressLowering"); + private final long heapBase; private final Register heapBaseRegister; private final GraalHotSpotVMConfig config; + private final boolean generatePIC; @NodeInfo(cycles = CYCLES_0, size = SIZE_0) public static class HeapBaseNode extends FloatingNode implements LIRLowerable { @@ -75,10 +81,11 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } } - public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister) { - this.heapBase = config.getOopEncoding().base; + public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister, OptionValues options) { + this.heapBase = config.getOopEncoding().getBase(); this.config = config; - if (heapBase == 0 && !GeneratePIC.getValue()) { + this.generatePIC = GeneratePIC.getValue(options); + if (heapBase == 0 && !generatePIC) { this.heapBaseRegister = null; } else { this.heapBaseRegister = heapBaseRegister; @@ -87,33 +94,42 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { @Override protected boolean improve(AMD64AddressNode addr) { + + boolean result = false; + + while (super.improve(addr)) { + result = true; + } + if (addr.getScale() == Scale.Times1) { - if (addr.getBase() == null && addr.getIndex() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getIndex())) { + if (addr.getIndex() instanceof CompressionNode) { + if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase())) { + counterFoldedUncompressDuringAddressLowering.increment(); return true; } } - if (addr.getIndex() == null && addr.getBase() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getBase())) { + if (addr.getBase() instanceof CompressionNode) { + if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex())) { + counterFoldedUncompressDuringAddressLowering.increment(); return true; } } } - return super.improve(addr); + return result; } - private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression) { + private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other) { if (compression.getOp() == CompressionOp.Uncompress) { CompressEncoding encoding = compression.getEncoding(); - Scale scale = Scale.fromShift(encoding.shift); + Scale scale = Scale.fromShift(encoding.getShift()); if (scale == null) { return false; } - if (heapBaseRegister != null && encoding.base == heapBase) { - if (!GeneratePIC.getValue() || compression.stamp() instanceof ObjectStamp) { + if (heapBaseRegister != null && encoding.getBase() == heapBase) { + if ((!generatePIC || compression.stamp() instanceof ObjectStamp) && other == null) { // With PIC it is only legal to do for oops since the base value may be // different at runtime. ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister)); @@ -121,21 +137,25 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } else { return false; } - } else if (encoding.base != 0 || (GeneratePIC.getValue() && compression.stamp() instanceof KlassPointerStamp)) { - if (GeneratePIC.getValue()) { - ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); - addr.setBase(base); + } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp() instanceof KlassPointerStamp)) { + if (generatePIC) { + if (other == null) { + ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); + addr.setBase(base); + } else { + return false; + } } else { - long disp = addr.getDisplacement() + encoding.base; + long disp = addr.getDisplacement() + encoding.getBase(); if (NumUtil.isInt(disp)) { addr.setDisplacement((int) disp); - addr.setBase(null); + addr.setBase(other); } else { return false; } } } else { - addr.setBase(null); + addr.setBase(other); } addr.setScale(scale); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java index b14f17795be..3e011324fd1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.amd64; +import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10; @@ -31,7 +32,6 @@ import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.Int import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.Variable; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import jdk.vm.ci.meta.Value; @@ -39,7 +39,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathLog(Value input, boolean base10) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathLog(input, base10); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -49,7 +49,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathCos(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathCos(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -59,7 +59,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathSin(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathSin(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -69,7 +69,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathTan(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathTan(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java index 7cb4b03b27e..ec145953af0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -30,8 +30,6 @@ import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.code.ValueUtil.asRegister; -import java.util.Set; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; @@ -66,6 +64,8 @@ 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.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -170,7 +170,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } else { asm.decrementq(rsp, frameSize); } - if (ZapStackOnMethodEntry.getValue()) { + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { final int intSize = 4; for (int i = 0; i < frameSize / intSize; ++i) { asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1); @@ -208,13 +208,14 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen; LIR lir = gen.getLIR(); assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; - boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); + OptionValues options = lir.getOptions(); + boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); Stub stub = gen.getStub(); Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -223,7 +224,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } if (stub != null) { - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); } @@ -268,7 +269,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { if (config.useCompressedClassPointers) { Register register = r10; AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1)); crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS); } else { @@ -289,7 +290,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { asm.bind(verifiedEntry); crb.recordMark(config.MARKID_VERIFIED_ENTRY); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { // Check for method state HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; if (!frameContext.isStub) { @@ -334,13 +335,13 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull); + return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { return calleeRegisters; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java index 96f90d0d7fe..ed56a74213b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java @@ -22,9 +22,8 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static jdk.vm.ci.common.InitTimer.timer; - +import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import java.util.ArrayList; import java.util.List; @@ -36,6 +35,7 @@ import org.graalvm.compiler.hotspot.HotSpotBackend; 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.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins; @@ -47,11 +47,10 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins; @@ -90,6 +89,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotBackend host) { assert host == null; + OptionValues options = graalRuntime.getOptions(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); HotSpotProviders providers; @@ -107,7 +107,6 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { HotSpotSuitesProvider suites; HotSpotWordTypes wordTypes; Plugins plugins; - NodeCostProvider nodeCostProvider; BytecodeProvider bytecodeProvider; try (InitTimer t = timer("create providers")) { try (InitTimer rt = timer("create HotSpotRegisters provider")) { @@ -125,11 +124,8 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { try (InitTimer rt = timer("create Lowerer provider")) { lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, target); } - try (InitTimer rt = timer("create NodeCost provider")) { - nodeCostProvider = createNodeCostProvider(target); - } HotSpotStampProvider stampProvider = new HotSpotStampProvider(); - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, nodeCostProvider); + Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider); try (InitTimer rt = timer("create SnippetReflection provider")) { snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes); @@ -138,16 +134,17 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(p, snippetReflection, bytecodeProvider); + replacements = createReplacements(options, p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, + stampProvider); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { - suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements); + suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options); } - providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, nodeCostProvider, suites, registers, + providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); } @@ -156,12 +153,11 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { } } - protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, - HotSpotHostForeignCallsProvider foreignCalls, - HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, - HotSpotStampProvider stampProvider) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - AMD64GraphBuilderPlugins.register(plugins, replacements.getReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue()); + protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target, + HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options)); return plugins; } @@ -173,8 +169,8 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp); } - protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, @@ -186,8 +182,9 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { * @param replacements */ protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, - HotSpotRegistersProvider registers, Replacements replacements) { - return new HotSpotSuitesProvider(new AMD64HotSpotSuitesProvider(compilerConfiguration, plugins), config, runtime, new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister())); + HotSpotRegistersProvider registers, Replacements replacements, OptionValues options) { + return new AddressLoweringHotSpotSuitesProvider(new AMD64HotSpotSuitesCreator(compilerConfiguration, plugins), config, runtime, + new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options)); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { @@ -199,10 +196,6 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, target); } - protected HotSpotNodeCostProvider createNodeCostProvider(TargetDescription target) { - return new AMD64HotSpotNodeCostProvider(target); - } - protected Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig regConfig) { List callerSave = new ArrayList<>(regConfig.getAllocatableRegisters().asList()); if (config.windowsOs) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java deleted file mode 100644 index 30c8a7f07ee..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,124 +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.hotspot.amd64; - -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.amd64.AMD64.rax; -import static jdk.vm.ci.amd64.AMD64.rbp; -import static jdk.vm.ci.amd64.AMD64.rip; -import static jdk.vm.ci.code.ValueUtil.asRegister; - -import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.framemap.FrameMap; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.RegisterSaveLayout; -import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.JavaKind; - -/** - * Emits code that enters a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") -final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotEnterUnpackFramesStackFrameOp.class); - - private final Register threadRegister; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadLastJavaFpOffset; - @Alive(REG) AllocatableValue framePc; - @Alive(REG) AllocatableValue senderSp; - @Alive(REG) AllocatableValue senderFp; - - private final SaveRegistersOp saveRegisterOp; - - AMD64HotSpotEnterUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, - AllocatableValue senderSp, AllocatableValue senderFp, SaveRegistersOp saveRegisterOp) { - super(TYPE); - this.threadRegister = threadRegister; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; - this.framePc = framePc; - this.senderSp = senderSp; - this.senderFp = senderFp; - this.saveRegisterOp = saveRegisterOp; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - FrameMap frameMap = crb.frameMap; - RegisterConfig registerConfig = frameMap.getRegisterConfig(); - RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap); - Register stackPointerRegister = registerConfig.getFrameRegister(); - final int totalFrameSize = frameMap.totalFrameSize(); - - // Push return address. - masm.push(asRegister(framePc)); - - // Push base pointer. - masm.push(asRegister(senderFp)); - masm.movq(rbp, stackPointerRegister); - - /* - * Allocate a full sized frame. Since return address and base pointer are already in place - * (see above) we allocate two words less. - */ - masm.decrementq(stackPointerRegister, totalFrameSize - 2 * crb.target.wordSize); - - // Save return registers after moving the frame. - final int stackSlotSize = frameMap.getTarget().wordSize; - Register integerResultRegister = registerConfig.getReturnRegister(JavaKind.Long); - masm.movptr(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize), integerResultRegister); - - Register floatResultRegister = registerConfig.getReturnRegister(JavaKind.Double); - masm.movdbl(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize), floatResultRegister); - - // Set up last Java values. - masm.movq(new AMD64Address(threadRegister, threadLastJavaSpOffset), stackPointerRegister); - - /* - * Save the PC since it cannot easily be retrieved using the last Java SP after we aligned - * SP. Don't need the precise return PC here, just precise enough to point into this code - * blob. - */ - masm.leaq(rax, new AMD64Address(rip, 0)); - masm.movq(new AMD64Address(threadRegister, threadLastJavaPcOffset), rax); - - // Use BP because the frames look interpreted now. - masm.movq(new AMD64Address(threadRegister, threadLastJavaFpOffset), rbp); - - // Align the stack for the following unpackFrames call. - masm.andq(stackPointerRegister, -(crb.target.stackAlignment)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java index 3f9f2cded39..e92e17485dc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java @@ -22,21 +22,18 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rdx; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; +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.word.LocationIdentity.any; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; @@ -45,6 +42,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -75,7 +73,7 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -89,24 +87,20 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - link(new AMD64DeoptimizationStub(providers, target, config, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64UncommonTrapStub(providers, target, config, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - } - link(new AMD64MathStub(ARITHMETIC_LOG_STUB, providers, registerStubCall(ARITHMETIC_LOG_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, providers, registerStubCall(ARITHMETIC_LOG10_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_SIN_STUB, providers, registerStubCall(ARITHMETIC_SIN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_COS_STUB, providers, registerStubCall(ARITHMETIC_COS_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_TAN_STUB, providers, registerStubCall(ARITHMETIC_TAN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_EXP_STUB, providers, registerStubCall(ARITHMETIC_EXP_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_POW_STUB, providers, registerStubCall(ARITHMETIC_POW_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); if (config.useCRC32Intrinsics) { // This stub does callee saving registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index bd87349a2d4..6144fb94954 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -22,29 +22,27 @@ */ package org.graalvm.compiler.hotspot.amd64; +import static jdk.vm.ci.amd64.AMD64.rbp; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static jdk.vm.ci.amd64.AMD64.rbp; import java.util.ArrayList; import java.util.List; -import java.util.Map; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.amd64.AMD64LIRGenerator; +import org.graalvm.compiler.core.amd64.AMD64LIRKindTool; import org.graalvm.compiler.core.amd64.AMD64MoveFactoryBase.BackupSlotProvider; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; @@ -55,7 +53,6 @@ import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.type.HotSpotLIRKindTool; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRFrameState; @@ -63,7 +60,6 @@ import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.StandardOp.NoOp; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; @@ -81,6 +77,7 @@ import org.graalvm.compiler.lir.amd64.AMD64VZeroUpper; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -114,7 +111,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp } private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) { - this(new AMD64HotSpotLIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); + this(new AMD64LIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); } protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, @@ -294,34 +291,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp super.emitForeignCallOp(linkage, result, arguments, temps, info); } - @Override - public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - append(new AMD64HotSpotLeaveCurrentStackFrameOp(saveRegisterOp)); - } - - @Override - public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable initialInfoVariable = load(initialInfo); - append(new AMD64HotSpotLeaveDeoptimizedStackFrameOp(frameSizeVariable, initialInfoVariable)); - } - - @Override - public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable senderFpVariable = load(senderFp); - append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable, - senderSpVariable, senderFpVariable, saveRegisterOp)); - } - - @Override - public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), saveRegisterOp)); - } - /** * @param savedRegisters the registers saved by this operation which may be subject to pruning * @param savedRegisterLocations the slots to which the registers are saved @@ -359,13 +328,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); } - @Override - public SaveRegistersOp emitSaveAllRegisters() { - // We are saving all registers. - // TODO Save upper half of YMM registers. - return emitSaveAllRegisters(target().arch.getAvailableValueRegisters().toArray(), false); - } - protected void emitRestoreRegisters(AMD64SaveRegistersOp save) { append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save)); } @@ -421,8 +383,12 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp if (stub != null) { if (stub.preservesRegisters()) { HotSpotLIRGenerationResult generationResult = getResult(); - assert !generationResult.getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); - generationResult.getCalleeSaveInfo().put(currentRuntimeCallInfo, save); + LIRFrameState key = currentRuntimeCallInfo; + if (key == null) { + key = LIRFrameState.NO_STATE; + } + assert !generationResult.getCalleeSaveInfo().containsKey(key); + generationResult.getCalleeSaveInfo().put(key, save); emitRestoreRegisters(save); } } @@ -434,8 +400,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp @Override public Value emitLoadObjectAddress(Constant constant) { HotSpotObjectConstant objectConstant = (HotSpotObjectConstant) constant; - HotSpotLIRKindTool kindTool = (HotSpotLIRKindTool) getLIRKindTool(); - LIRKind kind = objectConstant.isCompressed() ? kindTool.getNarrowOopKind() : kindTool.getObjectKind(); + LIRKind kind = objectConstant.isCompressed() ? getLIRKindTool().getNarrowOopKind() : getLIRKindTool().getObjectKind(); Variable result = newVariable(kind); append(new AMD64HotSpotLoadAddressOp(result, constant, HotSpotConstantLoadAction.RESOLVE)); return result; @@ -444,8 +409,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp @Override public Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) { HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; - HotSpotLIRKindTool kindTool = (HotSpotLIRKindTool) getLIRKindTool(); - LIRKind kind = metaspaceConstant.isCompressed() ? kindTool.getNarrowPointerKind() : kindTool.getWordKind(); + LIRKind kind = metaspaceConstant.isCompressed() ? getLIRKindTool().getNarrowPointerKind() : getLIRKindTool().getWordKind(); Variable result = newVariable(kind); append(new AMD64HotSpotLoadAddressOp(result, constant, action)); return result; @@ -510,38 +474,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp return emitMove(timestamp.getLowResult()); } - @Override - public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); - - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(AMD64Kind.QWORD)), trapRequest, mode); - append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), config.threadLastJavaPcOffset(), thread)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - - @Override - public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); - - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(AMD64Kind.QWORD)), mode); - append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), config.threadLastJavaPcOffset(), thread)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - @Override public void emitTailcall(Value[] args, Value address) { append(new AMD64TailcallOp(args, address)); @@ -621,21 +553,12 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp LIRInstruction op = getOrInitRescueSlotOp(); // insert dummy instruction into the start block LIR lir = getResult().getLIR(); - List instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); + ArrayList instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); instructions.add(1, op); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "created rescue dummy op"); + Debug.dump(Debug.INFO_LEVEL, lir, "created rescue dummy op"); } } - @Override - public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable initialInfoVariable = load(initialInfo); - append(new AMD64HotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable, config)); - } - @Override public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { LIRKind inputKind = pointer.getValueKind(LIRKind.class); @@ -649,14 +572,15 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0 || GeneratePIC.getValue()) { - if (GeneratePIC.getValue()) { + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); append(move); base = baseAddress; } else { - base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.base)); + base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } } append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); @@ -677,14 +601,15 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(AMD64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0 || GeneratePIC.getValue()) { - if (GeneratePIC.getValue()) { + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); append(move); base = baseAddress; } else { - base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.base)); + base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } } append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); @@ -697,9 +622,10 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp if (address.getValueKind().getPlatformKind() == AMD64Kind.DWORD) { CompressEncoding encoding = config.getOopEncoding(); Value uncompressed; - if (encoding.shift <= 3) { + if (encoding.getShift() <= 3) { LIRKind wordKind = LIRKind.unknownReference(target().arch.getWordKind()); - uncompressed = new AMD64AddressValue(wordKind, getProviders().getRegisters().getHeapBaseRegister().asValue(wordKind), asAllocatable(address), Scale.fromInt(1 << encoding.shift), 0); + uncompressed = new AMD64AddressValue(wordKind, getProviders().getRegisters().getHeapBaseRegister().asValue(wordKind), asAllocatable(address), Scale.fromInt(1 << encoding.getShift()), + 0); } else { uncompressed = emitUncompress(address, encoding, false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java deleted file mode 100644 index 40155af38f3..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,87 +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.hotspot.amd64; - -import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.framemap.FrameMap; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.RegisterSaveLayout; -import jdk.vm.ci.meta.JavaKind; - -/** - * Emits code that leaves a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") -final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotLeaveUnpackFramesStackFrameOp.class); - - private final Register threadRegister; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadLastJavaFpOffset; - - private final SaveRegistersOp saveRegisterOp; - - AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, SaveRegistersOp saveRegisterOp) { - super(TYPE); - this.threadRegister = threadRegister; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; - this.saveRegisterOp = saveRegisterOp; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - FrameMap frameMap = crb.frameMap; - RegisterConfig registerConfig = frameMap.getRegisterConfig(); - RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap); - Register stackPointerRegister = registerConfig.getFrameRegister(); - - // Restore stack pointer. - masm.movq(stackPointerRegister, new AMD64Address(threadRegister, threadLastJavaSpOffset)); - - // Clear last Java frame values. - masm.movslq(new AMD64Address(threadRegister, threadLastJavaSpOffset), 0); - masm.movslq(new AMD64Address(threadRegister, threadLastJavaPcOffset), 0); - masm.movslq(new AMD64Address(threadRegister, threadLastJavaFpOffset), 0); - - // Restore return values. - final int stackSlotSize = frameMap.getTarget().wordSize; - Register integerResultRegister = registerConfig.getReturnRegister(JavaKind.Long); - masm.movptr(integerResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize)); - - Register floatResultRegister = registerConfig.getReturnRegister(JavaKind.Double); - masm.movdbl(floatResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java index 24b11237bda..ae36c40fbdc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java @@ -51,7 +51,7 @@ public final class AMD64HotSpotLoadConfigValueOp extends AMD64LIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { AMD64Kind kind = (AMD64Kind) result.getPlatformKind(); Register reg = asRegister(result); AMD64Address placeholder = masm.getPlaceholder(-1); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java index 36292b06fc3..a548bd5ad22 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java @@ -27,8 +27,8 @@ import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvide import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB; +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; @@ -43,6 +43,7 @@ import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; @@ -62,10 +63,11 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - convertSnippets = new AMD64ConvertSnippets.Templates(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue() ? new ProbabilisticProfileSnippets.Templates(providers, providers.getCodeCache().getTarget()) : null; - super.initialize(providers, config); + public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { + convertSnippets = new AMD64ConvertSnippets.Templates(options, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) + ? new ProbabilisticProfileSnippets.Templates(options, providers, providers.getCodeCache().getTarget()) : null; + super.initialize(options, providers, config); } @Override @@ -81,7 +83,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider @Override protected ForeignCallDescriptor toForeignCall(UnaryOperation operation) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(runtime.getOptions())) { switch (operation) { case LOG: return ARITHMETIC_LOG_STUB; @@ -105,7 +107,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider @Override protected ForeignCallDescriptor toForeignCall(BinaryOperation operation) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(runtime.getOptions())) { switch (operation) { case POW: return ARITHMETIC_POW_STUB; @@ -118,7 +120,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider } @Override - public boolean supportSubwordCompare(int bits) { - return true; + public Integer smallestCompareWidth() { + return 8; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java index 168282ebcbf..a5c75f5958b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java @@ -34,9 +34,9 @@ import static jdk.vm.ci.code.ValueUtil.isStackSlot; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; @@ -67,7 +67,7 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { throw GraalError.shouldNotReachHere("Object constant load should not be happening directly"); } boolean compressed = input.isCompressed(); @@ -146,7 +146,7 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { throw GraalError.shouldNotReachHere("Metaspace constant load should not be happening directly"); } boolean compressed = input.isCompressed(); @@ -204,7 +204,7 @@ public class AMD64HotSpotMove { AMD64Move.move(AMD64Kind.QWORD, crb, masm, result, input); Register resReg = asRegister(result); - if (encoding.base != 0 || GeneratePIC.getValue()) { + if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { Register baseReg = asRegister(baseRegister); if (!nonNull) { masm.testq(resReg, resReg); @@ -213,8 +213,8 @@ public class AMD64HotSpotMove { masm.subq(resReg, baseReg); } - if (encoding.shift != 0) { - masm.shrq(resReg, encoding.shift); + if (encoding.hasShift()) { + masm.shrq(resReg, encoding.getShift()); } } } @@ -243,15 +243,15 @@ public class AMD64HotSpotMove { AMD64Move.move(AMD64Kind.DWORD, crb, masm, result, input); Register resReg = asRegister(result); - if (encoding.shift != 0) { - masm.shlq(resReg, encoding.shift); + if (encoding.getShift() != 0) { + masm.shlq(resReg, encoding.getShift()); } - if (encoding.base != 0 || GeneratePIC.getValue()) { + if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { if (nonNull) { masm.addq(resReg, asRegister(baseRegister)); } else { - if (encoding.shift == 0) { + if (!encoding.hasShift()) { // if encoding.shift != 0, the flags are already set by the shlq masm.testq(resReg, resReg); } @@ -268,17 +268,17 @@ public class AMD64HotSpotMove { public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) { CompressEncoding encoding = config.getKlassEncoding(); masm.movl(register, address); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Decode algorithm is wrong"; - masm.shlq(register, encoding.alignment); + if (encoding.getShift() != 0) { + masm.shlq(register, encoding.getShift()); } - if (GeneratePIC.getValue() || encoding.base != 0) { - if (GeneratePIC.getValue()) { + boolean pic = GeneratePIC.getValue(crb.getOptions()); + if (pic || encoding.hasBase()) { + if (pic) { masm.movq(scratch, masm.getPlaceholder(-1)); crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); } else { - assert encoding.base != 0; - masm.movq(scratch, encoding.base); + assert encoding.getBase() != 0; + masm.movq(scratch, encoding.getBase()); } masm.addq(register, scratch); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java index 893a35263f8..45ea897cd95 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java @@ -40,11 +40,13 @@ public class AMD64HotSpotMoveFactory extends AMD64MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; } else if (c instanceof HotSpotObjectConstant) { return ((HotSpotObjectConstant) c).isCompressed(); + } else if (c instanceof HotSpotMetaspaceConstant) { + return ((HotSpotMetaspaceConstant) c).isCompressed(); } else { return super.canInlineConstant(c); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeCostProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeCostProvider.java deleted file mode 100644 index 24e7d674b37..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeCostProvider.java +++ /dev/null @@ -1,93 +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.hotspot.amd64; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_15; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_6; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_80; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_30; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; -import org.graalvm.compiler.nodeinfo.NodeCycles; -import org.graalvm.compiler.nodeinfo.NodeSize; -import org.graalvm.compiler.nodes.ReturnNode; -import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; -import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; - -import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.amd64.AMD64.CPUFeature; -import jdk.vm.ci.code.TargetDescription; - -public class AMD64HotSpotNodeCostProvider extends HotSpotNodeCostProvider { - private final boolean avx2; - private final boolean sse41; - - public AMD64HotSpotNodeCostProvider(TargetDescription target) { - this.avx2 = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX2); - this.sse41 = ((AMD64) target.arch).getFeatures().contains(CPUFeature.SSE4_1); - } - - @Override - public NodeCycles cycles(Node n) { - if (n instanceof UnaryMathIntrinsicNode) { - UnaryMathIntrinsicNode u = (UnaryMathIntrinsicNode) n; - switch (u.getOperation()) { - case LOG: - case LOG10: - return CYCLES_15; - default: - break; - } - } else if (n instanceof ReturnNode) { - return CYCLES_6; - } else if (n instanceof ArrayEqualsNode) { - if (avx2) { - return CYCLES_50; - } else if (sse41) { - return CYCLES_80; - } - } - return super.cycles(n); - } - - @Override - public NodeSize size(Node n) { - if (n instanceof UnaryMathIntrinsicNode) { - UnaryMathIntrinsicNode u = (UnaryMathIntrinsicNode) n; - switch (u.getOperation()) { - case LOG: - case LOG10: - return SIZE_30; - default: - break; - } - } else if (n instanceof ReturnNode) { - return SIZE_4; - } - return super.size(n); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java index 09a6d98ba9c..b6e0f10fb2a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java @@ -36,13 +36,11 @@ import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.amd64.AMD64BreakpointOp; -import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -185,19 +183,6 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H } } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Value expected = gen.loadNonConst(operand(x.expectedValue())); - Variable newVal = gen.load(operand(x.newValue())); - assert expected.getValueKind().equals(newVal.getValueKind()); - - RegisterValue raxLocal = AMD64.rax.asValue(expected.getValueKind()); - gen.emitMove(raxLocal, expected); - append(new CompareAndSwapOp((AMD64Kind) expected.getPlatformKind(), raxLocal, getGen().asAddressValue(operand(x.getAddress())), raxLocal, newVal)); - - setResult(x, gen.emitMove(raxLocal)); - } - @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java index fd08e39b489..ce49590322e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java @@ -81,8 +81,8 @@ class AMD64HotSpotRegisterAllocationConfig extends RegisterAllocationConfig { }; // @formatter:on - AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java index 10321188ab0..7a5ee813a89 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.asm.NumUtil.isInt; +import static org.graalvm.compiler.core.common.NumUtil.isInt; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static jdk.vm.ci.amd64.AMD64.rax; @@ -63,7 +63,7 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { super(TYPE); this.state = state; this.config = config; - if (isPollingPageFar(config) || ImmutableCode.getValue()) { + if (isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) { temp = tool.getLIRGeneratorTool().newVariable(LIRKind.value(tool.getLIRGeneratorTool().target().arch.getWordKind())); } else { // Don't waste a register if it's unneeded @@ -87,13 +87,13 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { assert !atReturn || state == null : "state is unneeded at return"; - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(crb.getOptions())) { JavaKind hostWordKind = JavaKind.Long; int alignment = hostWordKind.getBitCount() / Byte.SIZE; JavaConstant pollingPageAddress = JavaConstant.forIntegerKind(hostWordKind, config.safepointPollingAddress); // This move will be patched to load the safepoint page from a data segment // co-located with the immutable code. - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { asm.movq(scratch, asm.getPlaceholder(-1)); } else { asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java similarity index 77% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java index 431d90ca4b9..5eedcf0f74f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java @@ -22,23 +22,24 @@ */ package org.graalvm.compiler.hotspot.amd64; -import org.graalvm.compiler.core.amd64.AMD64SuitesProvider; +import org.graalvm.compiler.core.amd64.AMD64SuitesCreator; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -public class AMD64HotSpotSuitesProvider extends AMD64SuitesProvider { +public class AMD64HotSpotSuitesCreator extends AMD64SuitesCreator { - public AMD64HotSpotSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public AMD64HotSpotSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } @Override - public LIRSuites createLIRSuites() { - LIRSuites lirSuites = super.createLIRSuites(); - if (GraalOptions.DetailedAsserts.getValue()) { + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites lirSuites = super.createLIRSuites(options); + if (GraalOptions.DetailedAsserts.getValue(options)) { lirSuites.getPostAllocationOptimizationStage().appendPhase(new HotSpotZapRegistersPhase()); } return lirSuites; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java index 15956d35052..39507dd2b63 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.SnippetStub; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; @@ -45,8 +46,8 @@ import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOpera */ public class AMD64MathStub extends SnippetStub { - public AMD64MathStub(ForeignCallDescriptor descriptor, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(snippetName(descriptor), providers, linkage); + public AMD64MathStub(ForeignCallDescriptor descriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetName(descriptor), options, providers, linkage); } private static String snippetName(ForeignCallDescriptor descriptor) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java index 2391ec6dd9c..4d51f5c734c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.amd64; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder; import org.graalvm.compiler.core.common.type.RawPointerStamp; @@ -32,6 +31,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -46,7 +46,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_20) +@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = NodeSize.SIZE_UNKNOWN) public final class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(AMD64RawNativeCallNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java deleted file mode 100644 index a4ca9d352e4..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.amd64; - -import static jdk.vm.ci.amd64.AMD64.r10; -import static jdk.vm.ci.amd64.AMD64.r11; -import static jdk.vm.ci.amd64.AMD64.r13; -import static jdk.vm.ci.amd64.AMD64.r14; -import static jdk.vm.ci.amd64.AMD64.r8; -import static jdk.vm.ci.amd64.AMD64.r9; -import static jdk.vm.ci.amd64.AMD64.rbx; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdi; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.rsi; - -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; - -final class AMD64UncommonTrapStub extends UncommonTrapStub { - - private RegisterConfig registerConfig; - - AMD64UncommonTrapStub(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - RegisterArray allocatable = new RegisterArray(rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14); - registerConfig = new AMD64HotSpotRegisterConfig(target, allocatable, config.windowsOs); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java deleted file mode 100644 index eb8e69b27fc..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.sparc; - -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; - -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.sparc.SPARCHotSpotRegisterConfig; - -final class SPARCDeoptimizationStub extends DeoptimizationStub { - - private RegisterConfig registerConfig; - - SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - // This is basically the maximum we can spare. All other G and O register are used. - RegisterArray allocatable = new RegisterArray(g1, g3, g4, g5, o0, o1, o2, o3, o4); - registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java index abe2d0ba2d7..a1b6cdf856b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java @@ -22,13 +22,6 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; -import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.sparc.SPARC.g0; @@ -40,10 +33,16 @@ import static jdk.vm.ci.sparc.SPARC.l7; import static jdk.vm.ci.sparc.SPARC.o0; import static jdk.vm.ci.sparc.SPARC.o7; import static jdk.vm.ci.sparc.SPARC.sp; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; +import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; +import java.util.ArrayList; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -62,11 +61,11 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -92,6 +91,10 @@ import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate; import org.graalvm.compiler.lir.sparc.SPARCTailDelayedLIRInstruction; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -203,7 +206,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { } } - if (ZapStackOnMethodEntry.getValue()) { + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { final int slotSize = 8; for (int i = 0; i < frameSize / slotSize; ++i) { // 0xC1C1C1C1 @@ -235,7 +238,8 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { // On SPARC we always use stack frames. HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + OptionValues options = lir.getOptions(); + CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -245,8 +249,8 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { if (stub != null) { // Even on sparc we need to save floating point registers - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); - Map calleeSaveInfo = gen.getCalleeSaveInfo(); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicMap calleeSaveInfo = gen.getCalleeSaveInfo(); updateStub(stub, destroyedCallerRegisters, calleeSaveInfo, frameMap); } assert registerSizePredictionValidator(crb); @@ -421,7 +425,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { * possible. */ private static void stuffDelayedControlTransfers(LIR l, AbstractBlockBase block) { - List instructions = l.getLIRforBlock(block); + ArrayList instructions = l.getLIRforBlock(block); if (instructions.size() >= 2) { LIRDependencyAccumulator acc = new LIRDependencyAccumulator(); SPARCDelayedControlTransfer delayedTransfer = null; @@ -497,14 +501,14 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull); + return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { - HashSet callerRegisters = new HashSet<>(calleeRegisters.size()); + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { + EconomicSet callerRegisters = EconomicSet.create(Equivalence.IDENTITY, calleeRegisters.size()); for (Register register : calleeRegisters) { if (l0.number <= register.number && register.number <= l7.number) { // do nothing diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java index 821348a75c3..eadc3cca4e8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java @@ -27,12 +27,13 @@ import java.util.Set; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.sparc.SPARCAddressLowering; -import org.graalvm.compiler.core.sparc.SPARCSuitesProvider; +import org.graalvm.compiler.core.sparc.SPARCSuitesCreator; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; 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; @@ -44,11 +45,9 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; 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.NodeCostProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; @@ -98,26 +97,25 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters); LoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, constantReflection, target); HotSpotStampProvider stampProvider = new HotSpotStampProvider(); - NodeCostProvider nodeCostProvider = new SPARCHotSpotNodeCostProvider(); - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, nodeCostProvider); + Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider); HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); - HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target); - Plugins plugins = createGraphBuilderPlugins(config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); + HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(runtime.getOptions(), p, snippetReflection, bytecodeProvider, target); + Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, nodeCostProvider, suites, registers, + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); return createBackend(config, runtime, providers); } - protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, - HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, - HotSpotWordTypes wordTypes) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - SPARCGraphBuilderPlugins.register(plugins, replacements.getReplacementBytecodeProvider()); + protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess, + HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider, + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + SPARCGraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider()); return plugins; } @@ -126,7 +124,7 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { */ protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, Replacements replacements) { - return new HotSpotSuitesProvider(new SPARCSuitesProvider(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering()); + return new AddressLoweringHotSpotSuitesProvider(new SPARCSuitesCreator(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering()); } protected SPARCHotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { @@ -142,10 +140,6 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(SPARC.g2, SPARC.g6, SPARC.sp); } - protected HotSpotNodeCostProvider createNodeCostProvider() { - return new SPARCHotSpotNodeCostProvider(); - } - @SuppressWarnings("unused") private static Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig regConfig) { Set callerSavedRegisters = new HashSet<>(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java deleted file mode 100644 index 418ea884fbe..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.STACK_BIAS; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARC.i0; -import static jdk.vm.ci.sparc.SPARC.i1; -import static jdk.vm.ci.sparc.SPARC.i2; -import static jdk.vm.ci.sparc.SPARC.i3; -import static jdk.vm.ci.sparc.SPARC.i4; -import static jdk.vm.ci.sparc.SPARC.l7; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; -import static jdk.vm.ci.sparc.SPARC.o5; -import static jdk.vm.ci.sparc.SPARC.o7; -import static jdk.vm.ci.sparc.SPARC.sp; - -import org.graalvm.compiler.asm.sparc.SPARCAddress; -import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.PlatformKind; - -/** - * Emits code that enters a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") -final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotEnterUnpackFramesStackFrameOp.class); - - private final Register thread; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - @Alive(REG) AllocatableValue framePc; - @Alive(REG) AllocatableValue senderSp; - @Temp(REG) AllocatableValue scratch; - @Temp(REG) AllocatableValue callerReturnPc; - - SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch, - PlatformKind wordKind) { - super(TYPE); - this.thread = thread; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.framePc = framePc; - this.senderSp = senderSp; - this.scratch = scratch; - callerReturnPc = o7.asValue(LIRKind.value(wordKind)); - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - final int totalFrameSize = crb.frameMap.totalFrameSize(); - Register framePcRegister = asRegister(framePc); - Register senderSpRegister = asRegister(senderSp); - Register scratchRegister = asRegister(scratch); - - // Save final sender SP to O5_savedSP. - masm.mov(senderSpRegister, o5); - - // Load final frame PC. - masm.mov(framePcRegister, asRegister(callerReturnPc)); - - // Allocate a full sized frame. - masm.save(sp, -totalFrameSize, sp); - - masm.mov(i0, o0); - masm.mov(i1, o1); - masm.mov(i2, o2); - masm.mov(i3, o3); - masm.mov(i4, o4); - - // Set up last Java values. - masm.add(sp, STACK_BIAS, scratchRegister); - masm.stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset)); - - // Clear last Java PC. - masm.stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)); - - /* - * Safe thread register manually since we are not using LEAF_SP for {@link - * DeoptimizationStub#UNPACK_FRAMES}. - */ - masm.mov(thread, l7); - } - - @Override - public boolean leavesRegisterWindow() { - return true; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java index 58a9bbe75c9..795119fe9ab 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java @@ -22,30 +22,27 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; import static jdk.vm.ci.sparc.SPARC.i0; import static jdk.vm.ci.sparc.SPARC.i1; import static jdk.vm.ci.sparc.SPARC.o0; import static jdk.vm.ci.sparc.SPARC.o1; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +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.word.LocationIdentity.any; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -69,7 +66,7 @@ public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -86,17 +83,12 @@ public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - link(new SPARCDeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - } - if (config.useCRC32Intrinsics) { // This stub does callee saving registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java index b6a2b520bc7..29a70ce9d17 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,66 +22,27 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; -import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; -import static jdk.vm.ci.sparc.SPARC.d32; -import static jdk.vm.ci.sparc.SPARC.d34; -import static jdk.vm.ci.sparc.SPARC.d36; -import static jdk.vm.ci.sparc.SPARC.d38; -import static jdk.vm.ci.sparc.SPARC.d40; -import static jdk.vm.ci.sparc.SPARC.d42; -import static jdk.vm.ci.sparc.SPARC.d44; -import static jdk.vm.ci.sparc.SPARC.d46; -import static jdk.vm.ci.sparc.SPARC.d48; -import static jdk.vm.ci.sparc.SPARC.d50; -import static jdk.vm.ci.sparc.SPARC.d52; -import static jdk.vm.ci.sparc.SPARC.d54; -import static jdk.vm.ci.sparc.SPARC.d56; -import static jdk.vm.ci.sparc.SPARC.d58; -import static jdk.vm.ci.sparc.SPARC.d60; -import static jdk.vm.ci.sparc.SPARC.d62; -import static jdk.vm.ci.sparc.SPARC.f0; -import static jdk.vm.ci.sparc.SPARC.f10; -import static jdk.vm.ci.sparc.SPARC.f12; -import static jdk.vm.ci.sparc.SPARC.f14; -import static jdk.vm.ci.sparc.SPARC.f16; -import static jdk.vm.ci.sparc.SPARC.f18; -import static jdk.vm.ci.sparc.SPARC.f2; -import static jdk.vm.ci.sparc.SPARC.f20; -import static jdk.vm.ci.sparc.SPARC.f22; -import static jdk.vm.ci.sparc.SPARC.f24; -import static jdk.vm.ci.sparc.SPARC.f26; -import static jdk.vm.ci.sparc.SPARC.f28; -import static jdk.vm.ci.sparc.SPARC.f30; -import static jdk.vm.ci.sparc.SPARC.f4; -import static jdk.vm.ci.sparc.SPARC.f6; -import static jdk.vm.ci.sparc.SPARC.f8; -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; +import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; -import java.util.Map; - +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.sparc.SPARCArithmeticLIRGenerator; import org.graalvm.compiler.core.sparc.SPARCLIRGenerator; +import org.graalvm.compiler.core.sparc.SPARCLIRKindTool; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; @@ -126,14 +87,13 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp final GraalHotSpotVMConfig config; private HotSpotDebugInfoBuilder debugInfoBuilder; - private LIRFrameState currentRuntimeCallInfo; public SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { this(providers, config, lirGenRes, new ConstantTableBaseProvider()); } private SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, ConstantTableBaseProvider constantTableBaseProvider) { - this(new SPARCHotSpotLIRKindTool(), new SPARCArithmeticLIRGenerator(), new SPARCHotSpotMoveFactory(constantTableBaseProvider), providers, config, lirGenRes, constantTableBaseProvider); + this(new SPARCLIRKindTool(), new SPARCArithmeticLIRGenerator(), new SPARCHotSpotMoveFactory(constantTableBaseProvider), providers, config, lirGenRes, constantTableBaseProvider); } public SPARCHotSpotLIRGenerator(LIRKindTool lirKindTool, SPARCArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, @@ -196,12 +156,6 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize()); } - @Override - protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { - currentRuntimeCallInfo = info; - super.emitForeignCallOp(linkage, result, arguments, temps, info); - } - @Override public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; @@ -280,7 +234,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); SPARCKind memKind = (SPARCKind) kind.getPlatformKind(); @@ -289,6 +243,15 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp return emitConditionalMove(memKind, expectedValue, result, Condition.EQ, true, trueValue, falseValue); } + @Override + public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + ValueKind kind = newValue.getValueKind(); + assert kind.equals(expectedValue.getValueKind()); + Variable result = newVariable(newValue.getValueKind()); + append(new CompareAndSwapOp(result, asAllocatable(address), asAllocatable(expectedValue), asAllocatable(newValue))); + return result; + } + @Override public void emitPrefetchAllocate(Value address) { SPARCAddressValue addr = asAddressValue(address); @@ -349,8 +312,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(WORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.getBase())); } append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -370,8 +333,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(XWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.getBase())); } append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -389,108 +352,6 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp return save; } - @Override - public SaveRegistersOp emitSaveAllRegisters() { - // We save all registers that were not saved by the save instruction. - // @formatter:off - Register[] savedRegisters = { - // CPU - g1, g3, g4, g5, - // FPU, use only every second register as doubles are stored anyways - f0, /*f1, */ f2, /*f3, */ f4, /*f5, */ f6, /*f7, */ - f8, /*f9, */ f10, /*f11,*/ f12, /*f13,*/ f14, /*f15,*/ - f16, /*f17,*/ f18, /*f19,*/ f20, /*f21,*/ f22, /*f23,*/ - f24, /*f25,*/ f26, /*f27,*/ f28, /*f29,*/ f30, /*f31 */ - d32, d34, d36, d38, - d40, d42, d44, d46, - d48, d50, d52, d54, - d56, d58, d60, d62 - }; - // @formatter:on - AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; - for (int i = 0; i < savedRegisters.length; i++) { - PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); - VirtualStackSlot spillSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); - savedRegisterLocations[i] = spillSlot; - } - return emitSaveRegisters(savedRegisters, savedRegisterLocations, false); - } - - @Override - public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - append(new SPARCHotSpotLeaveCurrentStackFrameOp()); - } - - @Override - public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp()); - } - - @Override - public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - Register thread = getProviders().getRegisters().getThreadRegister(); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable scratchVariable = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable, - target().arch.getWordKind())); - } - - @Override - public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset())); - } - - @Override - public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable initialInfoVariable = load(initialInfo); - append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); - } - - @Override - public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); - - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); - Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), trapRequest, mode); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert currentRuntimeCallInfo != null; - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - - @Override - public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); - - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); - Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), mode); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert currentRuntimeCallInfo != null; - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - @Override public void emitNullCheck(Value address, LIRFrameState state) { PlatformKind kind = address.getPlatformKind(); @@ -527,7 +388,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp } @Override - protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) { + protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, Variable scratchValue) { return new SPARCHotSpotStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java deleted file mode 100644 index 99f3826f361..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARC.i0; -import static jdk.vm.ci.sparc.SPARC.l7; - -import org.graalvm.compiler.asm.sparc.SPARCAddress; -import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction; -import org.graalvm.compiler.lir.sparc.SPARCSaveRegistersOp; - -import jdk.vm.ci.code.Register; - -/** - * Emits code that leaves a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") -final class SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotLeaveUnpackFramesStackFrameOp.class); - - private final Register thread; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadJavaFrameAnchorFlagsOffset; - - SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) { - super(TYPE); - this.thread = thread; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - /* - * Safe thread register manually since we are not using LEAF_SP for {@link - * DeoptimizationStub#UNPACK_FRAMES}. - */ - masm.mov(l7, thread); - - SPARCAddress lastJavaPc = new SPARCAddress(thread, threadLastJavaPcOffset); - - // We borrow the threads lastJavaPC to transfer the value from float to i0 - masm.stdf(SPARCSaveRegistersOp.RETURN_REGISTER_STORAGE, lastJavaPc); - masm.ldx(lastJavaPc, i0); - - // Clear last Java frame values. - masm.stx(g0, lastJavaPc); - masm.stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)); - masm.stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java index 7b869c46b9d..d6f9bdffaea 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; @@ -146,7 +146,7 @@ public class SPARCHotSpotMove { public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { Register inputRegister = asRegister(input); Register resReg = asRegister(result); - if (encoding.base != 0) { + if (encoding.hasBase()) { Register baseReg = asRegister(baseRegister); if (!nonNull) { masm.cmp(inputRegister, baseReg); @@ -155,11 +155,11 @@ public class SPARCHotSpotMove { } else { masm.sub(inputRegister, baseReg, resReg); } - if (encoding.shift != 0) { - masm.srlx(resReg, encoding.shift, resReg); + if (encoding.getShift() != 0) { + masm.srlx(resReg, encoding.getShift(), resReg); } } else { - masm.srlx(inputRegister, encoding.shift, resReg); + masm.srlx(inputRegister, encoding.getShift(), resReg); } } } @@ -189,14 +189,14 @@ public class SPARCHotSpotMove { Register inputRegister = asRegister(input); Register resReg = asRegister(result); Register secondaryInput; - if (encoding.shift != 0) { - masm.sll(inputRegister, encoding.shift, resReg); + if (encoding.getShift() != 0) { + masm.sll(inputRegister, encoding.getShift(), resReg); secondaryInput = resReg; } else { secondaryInput = inputRegister; } - if (encoding.base != 0) { + if (encoding.hasBase()) { if (nonNull) { masm.add(secondaryInput, asRegister(baseRegister), resReg); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java index 80545e36944..0be5caf20c9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java @@ -32,10 +32,10 @@ import org.graalvm.compiler.lir.LIRInstruction; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; public class SPARCHotSpotMoveFactory extends SPARCMoveFactory { @@ -44,10 +44,10 @@ public class SPARCHotSpotMoveFactory extends SPARCMoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; - } else if (c instanceof HotSpotObjectConstant) { + } else if (c instanceof HotSpotObjectConstant || c instanceof HotSpotMetaspaceConstant) { return false; } else { return super.canInlineConstant(c); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeCostProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeCostProvider.java deleted file mode 100644 index d2c3eca7968..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeCostProvider.java +++ /dev/null @@ -1,55 +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.hotspot.sparc; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; -import org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerNode; -import org.graalvm.compiler.nodeinfo.NodeCycles; -import org.graalvm.compiler.nodeinfo.NodeSize; -import org.graalvm.compiler.nodes.ReturnNode; - -public class SPARCHotSpotNodeCostProvider extends HotSpotNodeCostProvider { - - @Override - public NodeCycles cycles(Node n) { - if (n instanceof ReturnNode) { - return NodeCycles.CYCLES_6; - } else if (n instanceof JumpToExceptionHandlerNode) { - // restore caller window - return NodeCycles.CYCLES_3; - } - return super.cycles(n); - } - - @Override - public NodeSize size(Node n) { - if (n instanceof ReturnNode) { - return NodeSize.SIZE_4; - } else if (n instanceof JumpToExceptionHandlerNode) { - // restore caller window - return NodeSize.SIZE_3; - } - return super.size(n); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java index e16abf52bd2..8be13b7e173 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java @@ -36,14 +36,12 @@ import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.sparc.SPARCBreakpointOp; -import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.DirectCallTargetNode; @@ -90,18 +88,6 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H append(new SPARCHotSpotSafepointOp(info, getGen().config, gen)); } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); - AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); - AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); - assert cmpValue.getValueKind().equals(newValue.getValueKind()); - - Variable result = gen.newVariable(newValue.getValueKind()); - append(new CompareAndSwapOp(result, address, cmpValue, newValue)); - setResult(x, result); - } - @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java index 85fd975a91d..0265525c17e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java @@ -112,8 +112,8 @@ public class SPARCHotSpotRegisterAllocationConfig extends RegisterAllocationConf }; // @formatter:on - public SPARCHotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + public SPARCHotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java index fedd4a13673..f4e2c741782 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.g0; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CBCOND; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.INSTRUCTION_SIZE; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN; import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.g0; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; @@ -40,6 +40,7 @@ import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.SwitchStrategy; +import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.sparc.SPARCControlFlow; import org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer; @@ -54,7 +55,7 @@ import jdk.vm.ci.sparc.SPARC.CPUFeature; final class SPARCHotSpotStrategySwitchOp extends SPARCControlFlow.StrategySwitchOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotStrategySwitchOp.class); - SPARCHotSpotStrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { + SPARCHotSpotStrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, AllocatableValue key, Variable scratch) { super(TYPE, constantTableBase, strategy, keyTargets, defaultTarget, key, scratch); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java deleted file mode 100644 index 3ef27516389..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.sparc; - -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; - -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.sparc.SPARCHotSpotRegisterConfig; - -final class SPARCUncommonTrapStub extends UncommonTrapStub { - - private RegisterConfig registerConfig; - - SPARCUncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - // This is basically the maximum we can spare. All other G and O register are used. - RegisterArray allocatable = new RegisterArray(g1, g3, g4, g5, o0, o1, o2, o3, o4); - registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java index ec528b1c6f9..a08edd079c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java @@ -22,39 +22,29 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; -import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.tiers.Suites; -import org.graalvm.compiler.phases.tiers.SuitesProvider; -import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; /** * use @@ -74,14 +64,19 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { return AheadOfTimeCompilationTest.STATICFINALOBJECT; } + @Before + public void setUp() { + // Ignore on SPARC + Assume.assumeFalse("skipping on AArch64", getTarget().arch instanceof AArch64); + } + @Test public void testStaticFinalObjectAOT() { StructuredGraph result = compile("getStaticFinalObject", true); assertDeepEquals(1, getConstantNodes(result).count()); Stamp constantStamp = getConstantNodes(result).first().stamp(); Assert.assertTrue(constantStamp.toString(), constantStamp instanceof KlassPointerStamp); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -89,7 +84,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { StructuredGraph result = compile("getStaticFinalObject", false); assertDeepEquals(1, getConstantNodes(result).count()); assertDeepEquals(JavaKind.Object, getConstantNodes(result).first().getStackKind()); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -106,8 +100,7 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(AheadOfTimeCompilationTest.class); assertDeepEquals(type.klass(), filter.first().asConstant()); - assertDeepEquals(1, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(1, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -119,7 +112,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { JavaConstant c = filter.first().asJavaConstant(); Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), AheadOfTimeCompilationTest.class); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -135,8 +127,7 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { Stamp constantStamp = filter.first().stamp(); Assert.assertTrue(constantStamp instanceof KlassPointerStamp); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -147,7 +138,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { JavaConstant c = filter.first().asJavaConstant(); Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), Integer.TYPE); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -182,17 +172,18 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { return Boolean.valueOf(true); } - @Ignore("ImmutableCode override may not work reliably in non-hosted mode") @Test public void testBoxedBooleanAOT() { StructuredGraph result = compile("getBoxedBoolean", true); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(1, result.getNodes(PiNode.TYPE).count()); + assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); + assertDeepEquals(0, result.getNodes(PiNode.TYPE).count()); assertDeepEquals(1, getConstantNodes(result).count()); ConstantNode constant = getConstantNodes(result).first(); - assertDeepEquals(JavaKind.Long, constant.getStackKind()); - assertDeepEquals(((HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(Boolean.class)).klass(), constant.asConstant()); + assertDeepEquals(JavaKind.Object, constant.getStackKind()); + + JavaConstant c = constant.asJavaConstant(); + Assert.assertEquals(getSnippetReflection().asObject(Boolean.class, c), Boolean.TRUE); } @Test @@ -210,17 +201,9 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { @SuppressWarnings("try") private StructuredGraph compile(String test, boolean compileAOT) { - try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) { - StructuredGraph graph = parseEager(test, AllowAssumptions.YES); - ResolvedJavaMethod method = graph.method(); - // create suites everytime, as we modify options for the compiler - SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); - final Suites suitesLocal = suitesProvider.getDefaultSuites(); - final LIRSuites lirSuitesLocal = suitesProvider.getDefaultLIRSuites(); - final CompilationResult compResult = compileGraph(graph, method, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), - suitesLocal, lirSuitesLocal, new CompilationResult(), CompilationResultBuilderFactory.Default); - addMethod(method, compResult); - return graph; - } + OptionValues options = new OptionValues(getInitialOptions(), ImmutableCode, compileAOT); + StructuredGraph graph = parseEager(test, AllowAssumptions.YES, options); + compile(graph.method(), graph); + return graph; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java index e3ea0bc743b..952dd2bc08e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java @@ -26,9 +26,6 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySnippets; @@ -36,6 +33,9 @@ import org.graalvm.compiler.nodes.DirectCallTargetNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LoweredCallTargetNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.JavaMethod; @@ -47,10 +47,10 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g) { + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g, boolean forceCompile, boolean installAsDefault, OptionValues options) { StructuredGraph graph = g == null ? parseForCompile(method) : g; int nodeCount = graph.getNodeCount(); - InstalledCode result = super.getCode(method, graph); + InstalledCode result = super.getCode(method, graph, forceCompile, installAsDefault, options); boolean graphWasProcessed = nodeCount != graph.getNodeCount(); if (graphWasProcessed) { if (mustIntrinsify) { @@ -160,7 +160,7 @@ public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { } /** - * Tests {@link ArrayCopySnippets#checkcastArraycopyWork(Object, int, Object, int, int)}. + * Tests {@link ArrayCopySnippets#checkcastArraycopyWork}. */ @Test public void testArrayStoreException() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index 9a73893a4f5..60bd3e387f1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,15 +22,12 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERSION; - import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; @@ -44,7 +41,10 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; 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.test.GraalTest; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; @@ -55,11 +55,10 @@ import jdk.vm.ci.meta.MethodHandleAccessProvider.IntrinsicMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; /** - * Checks the set of intrinsics implemented by Graal against the set of intrinsics declared by - * HotSpot. The purpose of this test is to detect when new intrinsics are added to HotSpot and - * process them appropriately in Graal. This will be achieved by working through - * {@link #TO_BE_INVESTIGATED} and either implementing the intrinsic or moving it to {@link #IGNORE} - * . + * Checks the intrinsics implemented by Graal against the set of intrinsics declared by HotSpot. The + * purpose of this test is to detect when new intrinsics are added to HotSpot and process them + * appropriately in Graal. This will be achieved by working through {@link #TO_BE_INVESTIGATED} and + * either implementing the intrinsic or moving it to {@link #IGNORE} . */ public class CheckGraalIntrinsics extends GraalTest { @@ -74,11 +73,12 @@ public class CheckGraalIntrinsics extends GraalTest { return false; } - public static InvocationPlugin findPlugin(Map> bindings, VMIntrinsicMethod intrinsic) { - for (Map.Entry> e : bindings.entrySet()) { + public static InvocationPlugin findPlugin(EconomicMap> bindings, VMIntrinsicMethod intrinsic) { + MapCursor> cursor = bindings.getEntries(); + while (cursor.advance()) { // Match format of VMIntrinsicMethod.declaringClass - String type = MetaUtil.internalNameToJava(e.getKey(), true, false).replace('.', '/'); - for (Binding binding : e.getValue()) { + String type = MetaUtil.internalNameToJava(cursor.getKey(), true, false).replace('.', '/'); + for (Binding binding : cursor.getValue()) { if (match(type, binding, intrinsic)) { return binding.plugin; } @@ -246,21 +246,21 @@ public class CheckGraalIntrinsics extends GraalTest { "jdk/internal/misc/Unsafe.allocateUninitializedArray0(Ljava/lang/Class;I)Ljava/lang/Object;", "jdk/internal/misc/Unsafe.compareAndExchangeByteAcquire(Ljava/lang/Object;JBB)B", "jdk/internal/misc/Unsafe.compareAndExchangeByteRelease(Ljava/lang/Object;JBB)B", - "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B", + "jdk/internal/misc/Unsafe.compareAndExchangeByteVolatile(Ljava/lang/Object;JBB)B", "jdk/internal/misc/Unsafe.compareAndExchangeIntAcquire(Ljava/lang/Object;JII)I", "jdk/internal/misc/Unsafe.compareAndExchangeIntRelease(Ljava/lang/Object;JII)I", - "jdk/internal/misc/Unsafe.compareAndExchangeInt(Ljava/lang/Object;JII)I", + "jdk/internal/misc/Unsafe.compareAndExchangeIntVolatile(Ljava/lang/Object;JII)I", "jdk/internal/misc/Unsafe.compareAndExchangeLongAcquire(Ljava/lang/Object;JJJ)J", "jdk/internal/misc/Unsafe.compareAndExchangeLongRelease(Ljava/lang/Object;JJJ)J", - "jdk/internal/misc/Unsafe.compareAndExchangeLong(Ljava/lang/Object;JJJ)J", + "jdk/internal/misc/Unsafe.compareAndExchangeLongVolatile(Ljava/lang/Object;JJJ)J", "jdk/internal/misc/Unsafe.compareAndExchangeObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "jdk/internal/misc/Unsafe.compareAndExchangeObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.compareAndExchangeObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.compareAndExchangeObjectVolatile(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "jdk/internal/misc/Unsafe.compareAndExchangeShortAcquire(Ljava/lang/Object;JSS)S", "jdk/internal/misc/Unsafe.compareAndExchangeShortRelease(Ljava/lang/Object;JSS)S", - "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S", - "jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.compareAndSetShort(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.compareAndExchangeShortVolatile(Ljava/lang/Object;JSS)S", + "jdk/internal/misc/Unsafe.compareAndSwapByte(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.compareAndSwapShort(Ljava/lang/Object;JSS)Z", "jdk/internal/misc/Unsafe.copyMemory0(Ljava/lang/Object;JLjava/lang/Object;JJ)V", "jdk/internal/misc/Unsafe.getAndAddByte(Ljava/lang/Object;JB)B", "jdk/internal/misc/Unsafe.getAndAddShort(Ljava/lang/Object;JS)S", @@ -295,26 +295,26 @@ public class CheckGraalIntrinsics extends GraalTest { "jdk/internal/misc/Unsafe.putObjectOpaque(Ljava/lang/Object;JLjava/lang/Object;)V", "jdk/internal/misc/Unsafe.putShortOpaque(Ljava/lang/Object;JS)V", "jdk/internal/misc/Unsafe.unpark(Ljava/lang/Object;)V", - "jdk/internal/misc/Unsafe.weakCompareAndSetBytePlain(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetByteAcquire(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetByteRelease(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetByte(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntPlain(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntAcquire(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntRelease(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetInt(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongPlain(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongAcquire(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongRelease(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLong(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectPlain(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortPlain(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortAcquire(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortRelease(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShort(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapByte(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapByteAcquire(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapByteRelease(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapByteVolatile(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapInt(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapIntAcquire(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapIntRelease(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapIntVolatile(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapLong(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapLongAcquire(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapLongRelease(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapLongVolatile(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapObjectVolatile(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapShort(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapShortAcquire(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapShortRelease(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSwapShortVolatile(Ljava/lang/Object;JSS)Z", "jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I", "jdk/jfr/internal/JVM.counterTime()J", "jdk/jfr/internal/JVM.getBufferWriter()Ljava/lang/Object;", @@ -368,7 +368,7 @@ public class CheckGraalIntrinsics extends GraalTest { if (!config.useCRC32Intrinsics) { // Registration of the CRC32 plugins is guarded by UseCRC32Intrinsics add(IGNORE, "java/util/zip/CRC32.update(II)I"); - if (JAVA_SPECIFICATION_VERSION < 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { add(IGNORE, "java/util/zip/CRC32.updateByteBuffer(IJII)I", "java/util/zip/CRC32.updateBytes(I[BII)I"); @@ -380,7 +380,7 @@ public class CheckGraalIntrinsics extends GraalTest { "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I"); } } else { - if (JAVA_SPECIFICATION_VERSION >= 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION >= 9) { add(TO_BE_INVESTIGATED, "java/util/zip/CRC32C.updateBytes(I[BII)I", "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I"); @@ -389,7 +389,7 @@ public class CheckGraalIntrinsics extends GraalTest { if (!config.useAESIntrinsics) { // Registration of the AES plugins is guarded by UseAESIntrinsics - if (JAVA_SPECIFICATION_VERSION < 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { add(IGNORE, "com/sun/crypto/provider/AESCrypt.decryptBlock([BI[BI)V", "com/sun/crypto/provider/AESCrypt.encryptBlock([BI[BI)V", @@ -405,7 +405,7 @@ public class CheckGraalIntrinsics extends GraalTest { } if (!config.useMultiplyToLenIntrinsic()) { // Registration of the AES plugins is guarded by UseAESIntrinsics - if (JAVA_SPECIFICATION_VERSION < 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { add(IGNORE, "java/math/BigInteger.multiplyToLen([II[II[I)[I"); } else { add(IGNORE, "java/math/BigInteger.implMultiplyToLen([II[II[I)[I"); @@ -435,7 +435,7 @@ public class CheckGraalIntrinsics extends GraalTest { List intrinsics = store.getIntrinsics(); List missing = new ArrayList<>(); - Map> bindings = invocationPlugins.getBindings(true); + EconomicMap> bindings = invocationPlugins.getBindings(true); for (VMIntrinsicMethod intrinsic : intrinsics) { InvocationPlugin plugin = findPlugin(bindings, intrinsic); if (plugin == null) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java index 7b22ece7897..91d9690c601 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java @@ -48,7 +48,7 @@ public class ClassSubstitutionsTests extends GraalCompilerTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { throw Debug.handle(e); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java similarity index 64% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java index b2542607a3f..80ff0f20538 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java @@ -20,19 +20,15 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.hotspot; +package org.graalvm.compiler.hotspot.test; +import static java.util.Collections.singletonList; import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldClasspath; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldConfig; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldExcludeMethodFilter; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldMethodFilter; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldStartAt; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldStopAt; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldVerbose; +import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries; +import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import java.io.Closeable; import java.io.File; @@ -41,26 +37,22 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.net.URI; import java.net.URL; import java.net.URLClassLoader; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; +import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -77,21 +69,26 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.CompilerThreadFactory; import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; -import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.core.test.ReflectionOptionDescriptors; import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; -import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.hotspot.CompilationTask; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; -import org.graalvm.compiler.options.OptionsParser.OptionConsumer; +import org.graalvm.compiler.serviceprovider.JDK9Method; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.UnmodifiableEconomicMap; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotInstalledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -109,55 +106,35 @@ import jdk.vm.ci.runtime.JVMCICompiler; public final class CompileTheWorld { /** - * Magic token to denote that JDK classes are to be compiled. If {@link Util#Java8OrEarlier}, - * then the classes in {@code rt.jar} are compiled. Otherwise the classes in {@code - * /lib/modules} are compiled. + * 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. */ public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path"; /** - * A mechanism for overriding JVMCI options that affect compilation. A {@link Config} object - * should be used in a try-with-resources statement to ensure overriding of options is scoped - * properly. For example: - * - *

    -     *     Config config = ...;
    -     *     try (AutoCloseable s = config == null ? null : config.apply()) {
    -     *         // perform a JVMCI compilation
    -     *     }
    -     * 
    + * Magic token to denote the classes in the Java runtime image (i.e. in the {@code jrt:/} file + * system). */ - @SuppressWarnings("serial") - public static class Config extends HashMap, Object> implements OptionConsumer { - /** - * Creates a {@link Config} object by parsing a set of space separated override options. - * - * @param options a space separated set of option value settings with each option setting in - * a {@code -Dgraal.=} format but without the leading - * {@code -Dgraal.}. Ignored if null. - */ - public Config(String options) { - if (options != null) { - Map optionSettings = new HashMap<>(); - for (String optionSetting : options.split("\\s+|#")) { - OptionsParser.parseOptionSettingTo(optionSetting, optionSettings); - } - OptionsParser.parseOptions(optionSettings, this, ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader())); + public static final String JRT_CLASS_PATH_ENTRY = ""; + + /** + * @param options a space separated set of option value settings with each option setting in a + * {@code -Dgraal.=} format but without the leading {@code -Dgraal.}. + * Ignored if null. + */ + public static EconomicMap, Object> parseOptions(String options) { + if (options != null) { + EconomicMap optionSettings = EconomicMap.create(); + for (String optionSetting : options.split("\\s+|#")) { + OptionsParser.parseOptionSettingTo(optionSetting, optionSettings); } + EconomicMap, Object> values = OptionValues.newOptionMap(); + ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); + OptionsParser.parseOptions(optionSettings, values, loader); + return values; } - - /** - * Applies the overrides represented by this object. The overrides are in effect until - * {@link OverrideScope#close()} is called on the returned object. - */ - OverrideScope apply() { - return OptionValue.override(this); - } - - @Override - public void set(OptionDescriptor desc, Object value) { - put(desc.getOptionValue(), value); - } + return EconomicMap.create(); } private final HotSpotJVMCIRuntimeProvider jvmciRuntime; @@ -167,21 +144,21 @@ public final class CompileTheWorld { /** * Class path denoting classes to compile. * - * @see CompileTheWorldOptions#CompileTheWorldClasspath + * @see Options#Classpath */ private final String inputClassPath; /** * Class index to start compilation at. * - * @see CompileTheWorldOptions#CompileTheWorldStartAt + * @see Options#StartAt */ private final int startAt; /** * Class index to stop compilation at. * - * @see CompileTheWorldOptions#CompileTheWorldStopAt + * @see Options#StopAt */ private final int stopAt; @@ -198,7 +175,6 @@ public final class CompileTheWorld { private AtomicLong memoryUsed = new AtomicLong(); private boolean verbose; - private final Config config; /** * Signal that the threads should start compiling in multithreaded mode. @@ -207,6 +183,9 @@ public final class CompileTheWorld { private ThreadPoolExecutor threadPool; + private OptionValues currentOptions; + private final UnmodifiableEconomicMap, Object> compilationOptions; + /** * Creates a compile-the-world instance. * @@ -216,8 +195,8 @@ public final class CompileTheWorld { * @param methodFilters * @param excludeMethodFilters */ - public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, String files, Config config, int startAt, int stopAt, String methodFilters, - String excludeMethodFilters, boolean verbose) { + public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, String files, int startAt, int stopAt, String methodFilters, String excludeMethodFilters, + boolean verbose, OptionValues initialOptions, EconomicMap, Object> compilationOptions) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.inputClassPath = files; @@ -226,30 +205,40 @@ public final class CompileTheWorld { this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters); this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters); this.verbose = verbose; - this.config = config; + this.currentOptions = initialOptions; + + // Copy the initial options and add in any extra options + EconomicMap, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap()); + compilationOptionsCopy.putAll(compilationOptions); // We don't want the VM to exit when a method fails to compile... - config.putIfAbsent(ExitVMOnException, false); + ExitVMOnException.putIfAbsent(compilationOptionsCopy, false); // ...but we want to see exceptions. - config.putIfAbsent(PrintBailout, true); - config.putIfAbsent(PrintStackTraceOnException, true); + PrintBailout.putIfAbsent(compilationOptionsCopy, true); + PrintStackTraceOnException.putIfAbsent(compilationOptionsCopy, true); + + // By default only report statistics for the CTW threads themselves + GraalDebugConfig.Options.DebugValueThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld"); + this.compilationOptions = compilationOptionsCopy; } - public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler) { - this(jvmciRuntime, compiler, CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), CompileTheWorldStopAt.getValue(), - CompileTheWorldMethodFilter.getValue(), CompileTheWorldExcludeMethodFilter.getValue(), CompileTheWorldVerbose.getValue()); + public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) { + this(jvmciRuntime, compiler, Options.Classpath.getValue(options), + Options.StartAt.getValue(options), + Options.StopAt.getValue(options), + Options.MethodFilter.getValue(options), + Options.ExcludeMethodFilter.getValue(options), + Options.Verbose.getValue(options), + options, + parseOptions(Options.Config.getValue(options))); } /** * Compiles all methods in all classes in {@link #inputClassPath}. If {@link #inputClassPath} - * equals {@link #SUN_BOOT_CLASS_PATH} the boot class path is used. + * equals {@link #SUN_BOOT_CLASS_PATH} the boot classes are used. */ public void compile() throws Throwable { - // By default only report statistics for the CTW threads themselves - if (!GraalDebugConfig.Options.DebugValueThreadFilter.hasBeenSet()) { - GraalDebugConfig.Options.DebugValueThreadFilter.setValue("^CompileTheWorld"); - } if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) { String bcpEntry = null; if (Java8OrEarlier) { @@ -257,13 +246,15 @@ public final class CompileTheWorld { for (int i = 0; i < entries.length && bcpEntry == null; i++) { String entry = entries[i]; File entryFile = new File(entry); - // We stop at rt.jar, unless it is the first boot class path entry. if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) { bcpEntry = entry; } } + if (bcpEntry == null) { + throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH)); + } } else { - bcpEntry = System.getProperty("java.home") + "/lib/modules".replace('/', File.separatorChar); + bcpEntry = JRT_CLASS_PATH_ENTRY; } compile(bcpEntry); } else { @@ -413,92 +404,70 @@ public final class CompileTheWorld { } /** - * Name of the property that limits the set of modules processed by CompileTheWorld. + * A class path entry representing the {@code jrt:/} file system. */ - public static final String LIMITMODS_PROPERTY_NAME = "CompileTheWorld.limitmods"; + static class JRTClassPathEntry extends ClassPathEntry { - /** - * A class path entry that is a jimage file. - */ - static class ImageClassPathEntry extends ClassPathEntry { + private final String limitModules; - private final File jimage; - - ImageClassPathEntry(String name) { + JRTClassPathEntry(String name, String limitModules) { super(name); - jimage = new File(name); - assert jimage.isFile(); + this.limitModules = limitModules; } @Override public ClassLoader createClassLoader() throws IOException { - URL url = jimage.toURI().toURL(); + URL url = URI.create("jrt:/").toURL(); return new URLClassLoader(new URL[]{url}); } @Override public List getClassNames() throws IOException { - String prop = System.getProperty(LIMITMODS_PROPERTY_NAME); - Set limitmods = prop == null ? null : new HashSet<>(Arrays.asList(prop.split(","))); - List classNames = new ArrayList<>(); - String[] entries = readJimageEntries(); - for (String e : entries) { - if (e.endsWith(".class") && !e.endsWith("module-info.class")) { - assert e.charAt(0) == '/' : e; - int endModule = e.indexOf('/', 1); - assert endModule != -1 : e; - if (limitmods != null) { - String module = e.substring(1, endModule); - if (!limitmods.contains(module)) { - continue; - } + Set negative = new HashSet<>(); + Set positive = new HashSet<>(); + if (limitModules != null && !limitModules.isEmpty()) { + for (String s : limitModules.split(",")) { + if (s.startsWith("~")) { + negative.add(s.substring(1)); + } else { + positive.add(s); } - // Strip the module prefix and convert to dotted form - String className = e.substring(endModule + 1).replace('/', '.'); - // Strip ".class" suffix - className = className.replace('/', '.').substring(0, className.length() - ".class".length()); - classNames.add(className); } } + List classNames = new ArrayList<>(); + FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap()); + Path top = fs.getPath("/modules/"); + Files.find(top, Integer.MAX_VALUE, + (path, attrs) -> attrs.isRegularFile()).forEach(p -> { + int nameCount = p.getNameCount(); + if (nameCount > 2) { + String base = p.getName(nameCount - 1).toString(); + if (base.endsWith(".class") && !base.equals("module-info.class")) { + String module = p.getName(1).toString(); + if (positive.isEmpty() || positive.contains(module)) { + if (negative.isEmpty() || !negative.contains(module)) { + // Strip module prefix and convert to dotted form + String className = p.subpath(2, nameCount).toString().replace('/', '.'); + // Strip ".class" suffix + className = className.replace('/', '.').substring(0, className.length() - ".class".length()); + classNames.add(className); + } + } + } + } + }); return classNames; } - - private String[] readJimageEntries() { - try { - // Use reflection so this can be compiled on JDK8 - Path path = FileSystems.getDefault().getPath(name); - Method open = Class.forName("jdk.internal.jimage.BasicImageReader").getDeclaredMethod("open", Path.class); - Object reader = open.invoke(null, path); - Method getEntryNames = reader.getClass().getDeclaredMethod("getEntryNames"); - getEntryNames.setAccessible(true); - String[] entries = (String[]) getEntryNames.invoke(reader); - return entries; - } catch (Exception e) { - TTY.println("Error reading entries from " + name + ": " + e); - return new String[0]; - } - } } - /** - * Determines if a given path denotes a jimage file. - * - * @param path file path - * @return {@code true} if the 4 byte integer (in native endianness) at the start of - * {@code path}'s contents is {@code 0xCAFEDADA} - */ - static boolean isJImage(String path) { - try { - FileChannel channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ); - ByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); - map.order(ByteOrder.nativeOrder()).asIntBuffer().get(0); - int magic = map.asIntBuffer().get(0); - if (magic == 0xCAFEDADA) { - return true; - } - } catch (IOException e) { + private boolean isClassIncluded(String className) { + if (methodFilters != null && !MethodFilter.matchesClassName(methodFilters, className)) { + return false; } - return false; + if (excludeMethodFilters != null && MethodFilter.matchesClassName(excludeMethodFilters, className)) { + return false; + } + return true; } /** @@ -512,16 +481,6 @@ public final class CompileTheWorld { final String[] entries = classPath.split(File.pathSeparator); long start = System.currentTimeMillis(); - CompilerThreadFactory factory = new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { - @Override - public GraalDebugConfig getDebugConfig() { - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - return DebugEnvironment.initialize(System.out, compiler.getGraalRuntime().getHostProviders().getSnippetReflection()); - } - return null; - } - }); - try { // compile dummy method to get compiler initialized outside of the // config debug override. @@ -530,7 +489,7 @@ public final class CompileTheWorld { int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; boolean useProfilingInfo = false; boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault, currentOptions); task.runCompilation(); } catch (NoSuchMethodException | SecurityException e1) { printStackTrace(e1); @@ -541,26 +500,34 @@ public final class CompileTheWorld { * DebugValueThreadFilter to filter on the thread names. */ int threadCount = 1; - if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue()) { - threadCount = CompileTheWorldOptions.CompileTheWorldThreads.getValue(); + if (Options.MultiThreaded.getValue(currentOptions)) { + threadCount = Options.Threads.getValue(currentOptions); if (threadCount == 0) { threadCount = Runtime.getRuntime().availableProcessors(); } } else { running = true; } - threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); - try (OverrideScope s = config.apply()) { + OptionValues savedOptions = currentOptions; + currentOptions = new OptionValues(compilationOptions); + threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), + new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { + @Override + public GraalDebugConfig getDebugConfig() { + return DebugEnvironment.ensureInitialized(currentOptions, compiler.getGraalRuntime().getHostProviders().getSnippetReflection()); + } + })); + + try { for (int i = 0; i < entries.length; i++) { final String entry = entries[i]; ClassPathEntry cpe; if (entry.endsWith(".zip") || entry.endsWith(".jar")) { cpe = new JarClassPathEntry(entry); - } else if (isJImage(entry)) { - assert !Java8OrEarlier; - cpe = new ImageClassPathEntry(entry); + } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) { + cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions)); } else { if (!new File(entry).isDirectory()) { println("CompileTheWorld : Skipped classes in " + entry); @@ -610,17 +577,17 @@ public final class CompileTheWorld { } } catch (Throwable t) { // If something went wrong during pre-loading we just ignore it. - println("Preloading failed for (%d) %s: %s", classFileCounter, className, t); + if (isClassIncluded(className)) { + println("Preloading failed for (%d) %s: %s", classFileCounter, className, t); + } + continue; } /* * Only check filters after class loading and resolution to mitigate impact * on reproducibility. */ - if (methodFilters != null && !MethodFilter.matchesClassName(methodFilters, className)) { - continue; - } - if (excludeMethodFilters != null && MethodFilter.matchesClassName(excludeMethodFilters, className)) { + if (!isClassIncluded(className)) { continue; } @@ -650,12 +617,16 @@ public final class CompileTheWorld { } } } catch (Throwable t) { - println("CompileTheWorld (%d) : Skipping %s %s", classFileCounter, className, t.toString()); - printStackTrace(t); + if (isClassIncluded(className)) { + println("CompileTheWorld (%d) : Skipping %s %s", classFileCounter, className, t.toString()); + printStackTrace(t); + } } } cpe.close(); } + } finally { + currentOptions = savedOptions; } if (!running) { @@ -677,7 +648,7 @@ public final class CompileTheWorld { long elapsedTime = System.currentTimeMillis() - start; println(); - if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue()) { + if (Options.MultiThreaded.getValue(currentOptions)) { TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime, compileTime.get(), memoryUsed.get()); } else { @@ -712,8 +683,12 @@ public final class CompileTheWorld { @Override public void run() { waitToRun(); - try (OverrideScope s = config.apply()) { + OptionValues savedOptions = currentOptions; + currentOptions = new OptionValues(compilationOptions); + try { compileMethod(method, classFileCounter); + } finally { + currentOptions = savedOptions; } } }); @@ -734,7 +709,7 @@ public final class CompileTheWorld { // For more stable CTW execution, disable use of profiling information boolean useProfilingInfo = false; boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions); task.runCompilation(); // Invalidate the generated code so the code cache doesn't fill up @@ -783,8 +758,72 @@ public final class CompileTheWorld { return true; } + static class Options { + // @formatter:off + public static final OptionKey Help = new OptionKey<>(false); + public static final OptionKey Classpath = new OptionKey<>(CompileTheWorld.SUN_BOOT_CLASS_PATH); + public static final OptionKey Verbose = new OptionKey<>(true); + /** + * Ignore Graal classes by default to avoid problems associated with compiling + * snippets and method substitutions. + */ + public static final OptionKey LimitModules = new OptionKey<>("~jdk.internal.vm.compiler"); + public static final OptionKey Iterations = new OptionKey<>(1); + public static final OptionKey MethodFilter = new OptionKey<>(null); + public static final OptionKey ExcludeMethodFilter = new OptionKey<>(null); + public static final OptionKey StartAt = new OptionKey<>(1); + public static final OptionKey StopAt = new OptionKey<>(Integer.MAX_VALUE); + public static final OptionKey Config = new OptionKey<>(null); + public static final OptionKey MultiThreaded = new OptionKey<>(false); + public static final OptionKey Threads = new OptionKey<>(0); + + static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class, + "Help", "List options and their help messages and then exit.", + "Classpath", "Class path denoting methods to compile. Default is to compile boot classes.", + "Verbose", "Verbose operation.", + "LimitModules", "Comma separated list of module names to which compilation should be limited. " + + "Module names can be prefixed with \"~\" to exclude the named module.", + "Iterations", "The number of iterations to perform.", + "MethodFilter", "Only compile methods matching this filter.", + "ExcludeMethodFilter", "Exclude methods matching this filter from compilation.", + "StartAt", "First class to consider for compilation.", + "StopAt", "Last class to consider for compilation.", + "Config", "Option value overrides to use during compile the world. For example, " + + "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " + + "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.", + "MultiThreaded", "Run using multiple threads for compilation.", + "Threads", "Number of threads to use for multithreaded execution. Defaults to Runtime.getRuntime().availableProcessors()."); + // @formatter:on + } + + public static OptionValues loadOptions(OptionValues initialValues) { + EconomicMap, Object> values = OptionValues.newOptionMap(); + List loader = singletonList(DESCRIPTORS); + OptionsParser.parseOptions(extractEntries(System.getProperties(), "CompileTheWorld.", true), values, loader); + OptionValues options = new OptionValues(initialValues, values); + if (Options.Help.getValue(options)) { + options.printHelp(loader, System.out, "CompileTheWorld."); + System.exit(0); + } + return options; + } + public static void main(String[] args) throws Throwable { - HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler(); - compiler.compileTheWorld(); + HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); + HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) jvmciRuntime.getCompiler(); + HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); + HotSpotCodeCacheProvider codeCache = graalRuntime.getHostProviders().getCodeCache(); + OptionValues options = loadOptions(graalRuntime.getOptions()); + + int iterations = Options.Iterations.getValue(options); + for (int i = 0; i < iterations; i++) { + codeCache.resetCompilationStatistics(); + TTY.println("CompileTheWorld : iteration " + i); + + CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, options); + ctw.compile(); + } + // This is required as non-daemon threads can be started by class initializers + System.exit(0); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java index 481a3387af5..c7752050e7b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java @@ -23,13 +23,12 @@ package org.graalvm.compiler.hotspot.test; import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; - -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.hotspot.CompileTheWorld; -import org.graalvm.compiler.hotspot.CompileTheWorld.Config; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -41,11 +40,13 @@ public class CompileTheWorldTest extends GraalCompilerTest { @Test public void testJDK() throws Throwable { - boolean originalSetting = ExitVMOnException.getValue(); + boolean originalSetting = ExitVMOnException.getValue(getInitialOptions()); // Compile a couple classes in rt.jar HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); - System.setProperty(CompileTheWorld.LIMITMODS_PROPERTY_NAME, "java.base"); - new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, new Config("Inline=false"), 1, 5, null, null, true).compile(); - assert ExitVMOnException.getValue() == originalSetting; + System.setProperty("CompileTheWorld.LimitModules", "java.base"); + OptionValues initialOptions = getInitialOptions(); + EconomicMap, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false"); + new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile(); + assert ExitVMOnException.getValue(initialOptions) == originalSetting; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java index 3edc637a362..abd34e6397e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java @@ -23,12 +23,10 @@ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.util.ModuleAPI.addExports; -import static org.graalvm.compiler.core.common.util.ModuleAPI.getModule; +import static org.graalvm.compiler.test.JLModule.uncheckedAddExports; import java.lang.reflect.Method; -import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; @@ -36,15 +34,20 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.test.JLModule; import org.junit.BeforeClass; import org.junit.Test; - import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; + import jdk.vm.ci.meta.ResolvedJavaMethod; -public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements Opcodes { +public class ConstantPoolSubstitutionsTests extends GraalCompilerTest { + + public ConstantPoolSubstitutionsTests() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + } @SuppressWarnings("try") protected StructuredGraph test(final String snippet) { @@ -53,7 +56,7 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + Debug.dump(Debug.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { throw Debug.handle(e); @@ -105,67 +108,40 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements * This test uses some API hidden by the JDK9 module system. */ private static void addExports(Class c) { - if (!Util.Java8OrEarlier) { - Object javaBaseModule = getModule.invoke(String.class); - Object cModule = getModule.invoke(c); - addExports.invokeStatic(javaBaseModule, "jdk.internal.reflect", cModule); - addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", cModule); + if (!Java8OrEarlier) { + Object javaBaseModule = JLModule.fromClass(String.class); + Object cModule = JLModule.fromClass(c); + uncheckedAddExports(javaBaseModule, "jdk.internal.reflect", cModule); + uncheckedAddExports(javaBaseModule, "jdk.internal.misc", cModule); } } - /** - * Disables these tests until we know how to dynamically export the {@code jdk.internal.reflect} - * package from the {@code java.base} module to the unnamed module associated with - * {@link AsmLoader}. Without such an export, the test fails as follows: - * - *
    -     * Caused by: java.lang.IllegalAccessError: class org.graalvm.compiler.hotspot.test.ConstantPoolTest
    -     * (in unnamed module @0x57599b23) cannot access class jdk.internal.reflect.ConstantPool (in
    -     * module java.base) because module java.base does not export jdk.internal.reflect to unnamed
    -     * module @0x57599b23
    -     * 
    - */ - private static void assumeJDK8() { - // Assume.assumeTrue(Java8OrEarlier); - } - @Test public void testGetSize() { - assumeJDK8(); Object cp = getConstantPoolForObject(); test("getSize", cp); } @Test public void testGetIntAt() { - assumeJDK8(); test("getIntAt"); } @Test public void testGetLongAt() { - assumeJDK8(); test("getLongAt"); } @Test public void testGetFloatAt() { - assumeJDK8(); test("getFloatAt"); } @Test public void testGetDoubleAt() { - assumeJDK8(); test("getDoubleAt"); } - // @Test - public void testGetUTF8At() { - assumeJDK8(); - test("getUTF8At"); - } - private static final String PACKAGE_NAME = ConstantPoolSubstitutionsTests.class.getPackage().getName(); private static final String PACKAGE_NAME_INTERNAL = PACKAGE_NAME.replace('.', '/'); @@ -186,7 +162,7 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements if (loaded != null) { return loaded; } - byte[] bytes = generateClass(); + byte[] bytes = Gen.generateClass(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); @@ -194,131 +170,134 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements } } - // @formatter:off - /* - static class ConstantPoolTest { - public static int getSize(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getSize(); + static class Gen implements Opcodes { + // @formatter:off + /* + static class ConstantPoolTest { + public static int getSize(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getSize(); + } + + public static int getIntAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getIntAt(0); + } + + public static long getLongAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getLongAt(0); + } + + public static float getFloatAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getFloatAt(0); + } + + public static double getDoubleAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getDoubleAt(0); + } + + public static String getUTF8At(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getUTF8At(0); + } } + */ + // @formatter:on - public static int getIntAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getIntAt(0); + static byte[] generateClass() { + + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(52, ACC_SUPER, PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", null, "java/lang/Object", null); + cw.visitInnerClass(PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", PACKAGE_NAME_INTERNAL + "/ConstantPoolSubstitutionsTests", "ConstantPoolTest", + ACC_STATIC); + String constantPool = Java8OrEarlier ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool"; + + mv = cw.visitMethod(0, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getSize", "(Ljava/lang/Object;)I", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getSize", "()I", false); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getIntAt", "(Ljava/lang/Object;)I", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getIntAt", "(I)I", false); + mv.visitInsn(IRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getLongAt", "(Ljava/lang/Object;)J", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getLongAt", "(I)J", false); + mv.visitInsn(LRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getFloatAt", "(Ljava/lang/Object;)F", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getFloatAt", "(I)F", false); + mv.visitInsn(FRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getDoubleAt", "(Ljava/lang/Object;)D", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getDoubleAt", "(I)D", false); + mv.visitInsn(DRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getUTF8At", "(Ljava/lang/Object;)Ljava/lang/String;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getUTF8At", "(I)Ljava/lang/String;", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + cw.visitEnd(); + + return cw.toByteArray(); } - - public static long getLongAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getLongAt(0); - } - - public static float getFloatAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getFloatAt(0); - } - - public static double getDoubleAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getDoubleAt(0); - } - - public static String getUTF8At(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getUTF8At(0); - } - } - */ - // @formatter:on - private static byte[] generateClass() { - - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - - cw.visit(52, ACC_SUPER, PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", null, "java/lang/Object", null); - cw.visitInnerClass(PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", PACKAGE_NAME_INTERNAL + "/ConstantPoolSubstitutionsTests", "ConstantPoolTest", - ACC_STATIC); - String constantPool = Java8OrEarlier ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool"; - - mv = cw.visitMethod(0, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getSize", "(Ljava/lang/Object;)I", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getSize", "()I", false); - mv.visitInsn(IRETURN); - mv.visitMaxs(1, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getIntAt", "(Ljava/lang/Object;)I", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getIntAt", "(I)I", false); - mv.visitInsn(IRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getLongAt", "(Ljava/lang/Object;)J", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getLongAt", "(I)J", false); - mv.visitInsn(LRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getFloatAt", "(Ljava/lang/Object;)F", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getFloatAt", "(I)F", false); - mv.visitInsn(FRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getDoubleAt", "(Ljava/lang/Object;)D", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getDoubleAt", "(I)D", false); - mv.visitInsn(DRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getUTF8At", "(Ljava/lang/Object;)Ljava/lang/String;", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getUTF8At", "(I)Ljava/lang/String;", false); - mv.visitInsn(ARETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - cw.visitEnd(); - - return cw.toByteArray(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java index 445c48e2482..32675cc157c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java @@ -23,18 +23,16 @@ package org.graalvm.compiler.hotspot.test; -import org.junit.Assume; -import org.junit.Test; - -import org.graalvm.compiler.hotspot.CompressEncoding; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import org.junit.Assume; +import org.junit.Test; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -74,19 +72,18 @@ public class DataPatchTest extends HotSpotGraalCompilerTest { } @Override - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { Registration r = new Registration(invocationPlugins, DataPatchTest.class); r.register1("compressUncompress", Object.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { CompressEncoding encoding = runtime().getVMConfig().getOopEncoding(); - ValueNode compressed = b.add(CompressionNode.compress(arg, encoding)); + ValueNode compressed = b.add(HotSpotCompressionNode.compress(arg, encoding)); ValueNode proxy = b.add(new OpaqueNode(compressed)); - b.addPush(JavaKind.Object, CompressionNode.uncompress(proxy, encoding)); + b.addPush(JavaKind.Object, HotSpotCompressionNode.uncompress(proxy, encoding)); return true; } }); - return super.editGraphBuilderConfiguration(conf); + super.registerInvocationPlugins(invocationPlugins); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java new file mode 100644 index 00000000000..97b8543cd2b --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java @@ -0,0 +1,194 @@ +/* + * 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.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.hotspot.phases.aot.EliminateRedundantInitializationPhase; +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.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; + +public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest { + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins plugins = super.getDefaultGraphBuilderPlugins(); + plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); + return plugins; + } + + public static class X { + public static int x; + public static int y; + public static int z; + } + + public static class Y extends X { + public static int a; + public static int b; + } + + public static void assignFields() { + X.x = 1; + X.y = 2; + X.z = 3; + } + + public static void assignFieldsConditionally(boolean choice) { + X.x = 1; + if (choice) { + X.y = 2; + } else { + X.z = 3; + } + } + + public static void assignFieldsSubclassDominates() { + Y.a = 1; + X.x = 2; + X.y = 3; + X.z = 4; + } + + public static void assignFieldsConditionallySubclassDominates(boolean choice) { + Y.a = 1; + if (choice) { + X.x = 2; + } else { + X.y = 3; + } + Y.z = 4; + } + + public static void assignFieldsSubclassPostdominates() { + X.x = 1; + Y.a = 2; + } + + public static void assignFieldsConditionallySubclassPostdominates(boolean choice) { + X.x = 1; + if (choice) { + X.y = 2; + } else { + X.z = 3; + } + Y.a = 4; + } + + public static void assignFieldsConditionallyMixed(boolean choice) { + X.x = 1; + if (choice) { + Y.a = 2; + } else { + X.z = 3; + } + Y.b = 4; + } + + public static void assignFieldsInLoop() { + X.x = 1; + for (int i = 0; i < 10; i++) { + X.y += X.z; + } + } + + public static void assignFieldsInBranches(boolean choice) { + if (choice) { + X.x = 1; + } else { + X.y = 2; + } + X.z = 3; + } + + public static void assignFieldsInBranchesMixed(boolean choice) { + if (choice) { + X.x = 1; + } else { + Y.a = 2; + } + X.z = 3; + } + + private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) { + StructuredGraph graph = parseEager(name, AllowAssumptions.NO); + Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count()); + HighTierContext highTierContext = getDefaultHighTierContext(); + new EliminateRedundantInitializationPhase().apply(graph, highTierContext); + Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count()); + } + + @Test + public void test1() { + test("assignFields", 3, 1); + } + + @Test + public void test2() { + test("assignFieldsConditionally", 3, 1); + } + + @Test + public void test3() { + test("assignFieldsSubclassDominates", 4, 1); + } + + @Test + public void test4() { + test("assignFieldsConditionallySubclassDominates", 4, 1); + } + + @Test + public void test5() { + test("assignFieldsSubclassPostdominates", 2, 2); + } + + @Test + public void test6() { + test("assignFieldsConditionallySubclassPostdominates", 4, 2); + } + + @Test + public void test7() { + test("assignFieldsConditionallyMixed", 4, 3); + } + + @Test + public void test8() { + test("assignFieldsInLoop", 4, 1); + } + + @Test + public void test9() { + test("assignFieldsInBranches", 3, 2); + } + + @Test + public void test10() { + test("assignFieldsInBranchesMixed", 3, 2); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java index b1099a426e7..44dbfe55e67 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java @@ -25,7 +25,9 @@ package org.graalvm.compiler.hotspot.test; import org.junit.Test; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -35,8 +37,8 @@ public class ExplicitExceptionTest extends GraalCompilerTest { private int expectedForeignCallCount; @Override - protected InstalledCode getCode(ResolvedJavaMethod method) { - InstalledCode installedCode = super.getCode(method); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + InstalledCode installedCode = super.getCode(method, graph, forceCompile, installAsDefault, options); assertDeepEquals(expectedForeignCallCount, lastCompiledGraph.getNodes().filter(ForeignCallNode.class).count()); return installedCode; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java index 12c411f12a4..a623d56d927 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java @@ -30,9 +30,9 @@ import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -43,11 +43,9 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ForeignCallDeoptimizeTest extends GraalCompilerTest { @Override - protected Plugins getDefaultGraphBuilderPlugins() { + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { ForeignCallsProvider foreignCalls = ((HotSpotProviders) getProviders()).getForeignCalls(); - - Plugins ret = super.getDefaultGraphBuilderPlugins(); - ret.getInvocationPlugins().register(new InvocationPlugin() { + invocationPlugins.register(new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { @@ -56,7 +54,7 @@ public class ForeignCallDeoptimizeTest extends GraalCompilerTest { return true; } }, ForeignCallDeoptimizeTest.class, "testCallInt", int.class); - return ret; + super.registerInvocationPlugins(invocationPlugins); } public static int testCallInt(int value) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java index 5466a638e79..4834e51cfb3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java @@ -22,35 +22,652 @@ */ package org.graalvm.compiler.hotspot.test; -import org.junit.Ignore; -import org.junit.Test; +import java.lang.management.ManagementFactory; +import java.lang.management.MonitorInfo; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.phases.HighTier; +import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Test on-stack-replacement with locks. */ public class GraalOSRLockTest extends GraalOSRTestBase { - @Ignore("OSR with locks not supported") - @Test - public void testOSR() { - testOSR("test"); + private static boolean TestInSeparateThread = false; + + // testing only + public static boolean isMonitorLockHeld(Object o) { + return isMonitorLockHeldByThread(o, null); } - static int limit = 10000; + public static boolean isMonitorLockHeldByThread(Object o, Thread t) { + int oihc = System.identityHashCode(o); + ThreadMXBean tmxbean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] tinfos = tmxbean.dumpAllThreads(true, false); - private static Object lock = new Object(); - - public static ReturnValue test() { - synchronized (lock) { - for (int i = 0; i < limit * limit; i++) { - GraalDirectives.blackhole(i); - if (GraalDirectives.inCompiledCode()) { - return ReturnValue.SUCCESS; + for (ThreadInfo ti : tinfos) { + if (!(t != null && t.getId() != ti.getThreadId())) { + for (MonitorInfo mi : ti.getLockedMonitors()) { + if (mi.getIdentityHashCode() == oihc) { + return true; + } } } - return ReturnValue.FAILURE; + } + return false; + } + + protected static void run(Runnable r) { + if (TestInSeparateThread) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + beforeOSRLockTest(); + r.run(); + afterOSRLockTest(); + } + }); + t.start(); + try { + t.join(); + } catch (Throwable t1) { + throw new GraalError(t1); + } + } else { + beforeOSRLockTest(); + r.run(); + afterOSRLockTest(); + } + } + + private static boolean wasLocked() { + return isMonitorLockHeld(lock) || isMonitorLockHeld(lock1); + } + + protected static EconomicMap, Object> osrLockNoDeopt() { + EconomicMap, Object> overrides = OptionValues.newOptionMap(); + overrides.put(OnStackReplacementPhase.Options.DeoptAfterOSR, false); + overrides.put(OnStackReplacementPhase.Options.SupportOSRWithLocks, true); + return overrides; + } + + protected static EconomicMap, Object> osrLockDeopt() { + EconomicMap, Object> overrides = OptionValues.newOptionMap(); + overrides.put(OnStackReplacementPhase.Options.SupportOSRWithLocks, true); + return overrides; + } + + public static int SideEffectI; + + private static void lockOnObject(Object o, String msg) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + synchronized (o) { + SideEffectI = 1; + } + } + }); + t.start(); + try { + t.join(1000); + } catch (InterruptedException e) { + Assert.fail("Object " + msg + " was locked"); + } + } + + private static void beforeOSRLockTest() { + // try lock both objects + lockOnObject(lock, "lock"); + lockOnObject(lock1, "lock1"); + Assert.assertFalse(wasLocked()); + } + + private static void afterOSRLockTest() { + // try lock both objects + lockOnObject(lock, "lock"); + lockOnObject(lock1, "lock1"); + Assert.assertFalse(wasLocked()); + // force a safepoint and hope the inflated locks are deflated + System.gc(); + } + + @BeforeClass + public static void init() { + DebugEnvironment.ensureInitialized(getInitialOptions()); + } + + // @Test + @SuppressWarnings("try") + public void testLockOSROuterImmediateDeoptAfter() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + testOSR(options, "testOuterLockImmediateDeoptAfter"); + }); + } + + static class A { + + } + + static class B { + @SuppressWarnings("unused") + B(A a) { + + } + } + + HashMap> listeners = new HashMap<>(); + + public synchronized ReturnValue synchronizedSnippet() { + /* + * Test method for which liveness would conclude the original object is no longer alive + * although it is. + */ + Collection> allListeners = listeners.values(); + for (HashSet group : allListeners) { + GraalDirectives.blackhole(group); + } + return ReturnValue.SUCCESS; + } + + @Test + @SuppressWarnings("try") + public void testSynchronizedSnippet() { + GraalOSRLockTest instance = new GraalOSRLockTest(); + // enough entries to trigger OSR + for (int i = 0; i < 100000; i++) { + instance.listeners.put("hello" + i, null); + } + testOSR(getInitialOptions(), "synchronizedSnippet", instance); + Assert.assertFalse(isMonitorLockHeld(instance)); + } + + @Test + @SuppressWarnings("try") + public void testOSRTrivialLoop() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + try { + testOSR(options, "testReduceOSRTrivialLoop"); + } catch (Throwable t) { + Assert.assertEquals("OSR compilation without OSR entry loop.", t.getMessage()); + } + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerImmediateDeoptAfter() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + testOSR(options, "testOuterInnerLockImmediateDeoptAfter"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterCompileRestOfMethod() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerCompileRestOfMethod() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthCompileRestOfMethod() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterInnerLockDepth1CompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthDeopt() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterInnerLockDepth1DeoptAfter"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthRecursiveCompileRestOfMethod0() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockDepth1RecursiveCompileRestOfMethod1"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthRecursiveCompileRestOfMethod1() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockDepth1RecursiveCompileRestOfMethod2"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterCompileRestOfMethodSubsequentLock() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterLockCompileRestOfMethodSubsequentLock"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerSameLockCompileRestOfMethod() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerSameLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSRRecursive() { + run(() -> { + // call it + testRecursiveLockingLeaf(); + ResolvedJavaMethod leaf = getResolvedJavaMethod("testRecursiveLockingLeaf"); + // profile it + leaf.reprofile(); + testRecursiveLockingLeaf(); + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + compile(options, leaf, -1); + testOSR(options, "testRecursiveLockingRoot"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSRRecursiveLeafOSR() { + run(() -> { + testRecursiveRootNoOSR(); + ResolvedJavaMethod root = getResolvedJavaMethod("testRecursiveRootNoOSR"); + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + compile(options, root, -1); + testOSR(options, "testRecursiveLeafOSR"); + // force a safepoint and hope the inflated locks are deflated + System.gc(); + // call the root to call into the leaf and enter the osr-ed code + testRecursiveRootNoOSR(); + + }); + } + + protected static int limit = 10000; + protected static Object lock = new Object(); + protected static Object lock1 = new Object(); + private static final boolean LOG = false; + + static { + // force identity hash code for easy displaced mark identification + int h1 = System.identityHashCode(lock); + int h2 = System.identityHashCode(lock1); + if (LOG) { + TTY.println("Forcing a system identity hashcode on lock object " + h1); + TTY.println("Forcing a system identity hashcode on lock1 object " + h2); + } + } + + public static ReturnValue testReduceOSRTrivialLoop() { + for (int i = 0; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (GraalDirectives.inCompiledCode()) { + return ReturnValue.SUCCESS; + } + } + return ReturnValue.FAILURE; + } + + public static ReturnValue testOuterLockImmediateDeoptAfter() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + if (GraalDirectives.inCompiledCode()) { + throw new Error("Must not be part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockImmediateDeoptAfter() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (lock1) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + GraalDirectives.deoptimize(); + return ret; + } + } + + public static ReturnValue testOuterLockCompileRestOfMethod() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 1001 == 0) { + ret = ReturnValue.SUCCESS; + System.gc(); + } + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockCompileRestOfMethod() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (lock1) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + System.gc(); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1CompileRestOfMethod() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock1) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 1001 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (limit)) { + GraalDirectives.blackhole(ret); + System.gc(); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } else { + // lock 1 must be free + if (isMonitorLockHeld(lock1)) { + throw new Error("Lock 1 must have been released already"); + } + + // lock 2 must still be locked and cannot be acquired by another thread + if (!isMonitorLockHeldByThread(lock, Thread.currentThread())) { + throw new Error("Lock must not have been released already"); + } + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1DeoptAfter() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock1) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + GraalDirectives.deoptimize(); + if (GraalDirectives.inCompiledCode()) { + throw new Error("Must not part of compiled code"); + } + } + } + return ret; + } + + public static ReturnValue testOuterInnerLockDepth1RecursiveCompileRestOfMethod1() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1RecursiveCompileRestOfMethod2() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testRecursiveLockingRoot() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + testRecursiveLockingLeaf(); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testRecursiveLockingLeaf() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + } + return ret; + } + } + + public static ReturnValue testRecursiveRootNoOSR() { + // testing the order of the lock releasing + final Object l = lock; + synchronized (l) { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 0; i < 5; i++) { + if (GraalDirectives.inCompiledCode()) { + ret = testRecursiveLeafOSR(); + } + GraalDirectives.controlFlowAnchor(); + if (ret == ReturnValue.FAILURE) { + return ret; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } + + public static ReturnValue testRecursiveLeafOSR() { + ReturnValue ret = ReturnValue.FAILURE; + // lock is already locked by the caller + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } + + // test cases for optimizations + public static ReturnValue testOuterLockCompileRestOfMethodSubsequentLock() { + final Object monitor = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (monitor) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + synchronized (monitor) { + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + } + return ret; + + } + + public static ReturnValue testOuterInnerSameLockCompileRestOfMethod() { + final Object monitor = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (monitor) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (monitor) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java index 3ae96088676..a978dbf4bac 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.hotspot.test; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Assert; +import org.junit.Test; /** * Test on-stack-replacement with Graal. The test manually triggers a Graal OSR-compilation which is @@ -33,13 +33,29 @@ import org.graalvm.compiler.api.directives.GraalDirectives; public class GraalOSRTest extends GraalOSRTestBase { @Test - public void testOSR() { - testOSR("test"); + public void testOSR01() { + try { + testOSR(getInitialOptions(), "testReduceLoop"); + } catch (Throwable t) { + Assert.assertEquals("OSR compilation without OSR entry loop.", t.getMessage()); + } + } + + @Test + public void testOSR02() { + testOSR(getInitialOptions(), "testSequentialLoop"); + } + + @Test + public void testOSR03() { + testOSR(getInitialOptions(), "testNonReduceLoop"); } static int limit = 10000; - public static ReturnValue test() { + public static int sideEffect; + + public static ReturnValue testReduceLoop() { for (int i = 0; i < limit * limit; i++) { GraalDirectives.blackhole(i); if (GraalDirectives.inCompiledCode()) { @@ -49,4 +65,38 @@ public class GraalOSRTest extends GraalOSRTestBase { return ReturnValue.FAILURE; } + public static ReturnValue testSequentialLoop() { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 1; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 7 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + if (sideEffect == 123) { + return ReturnValue.SIDE; + } + for (int i = 1; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + + public static ReturnValue testNonReduceLoop() { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 0; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java index 9742ebd1e1d..3079cbacf9f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java @@ -23,19 +23,23 @@ package org.graalvm.compiler.hotspot.test; -import org.junit.Assert; +import java.util.Arrays; import org.graalvm.compiler.bytecode.Bytecode; +import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.hotspot.CompilationTask; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.java.BciBlockMapping; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; @@ -47,25 +51,29 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public abstract class GraalOSRTestBase extends GraalCompilerTest { - protected void testOSR(String methodName) { - ResolvedJavaMethod method = getResolvedJavaMethod(methodName); - testOSR(method); + protected void testOSR(OptionValues options, String methodName) { + testOSR(options, methodName, null); } - protected void testOSR(ResolvedJavaMethod method) { + protected void testOSR(OptionValues options, String methodName, Object receiver, Object... args) { + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + testOSR(options, method, receiver, args); + } + + protected void testOSR(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { // invalidate any existing compiled code method.reprofile(); - compileOSR(method); - Result result = executeExpected(method, null); + compileOSR(options, method); + Result result = executeExpected(method, receiver, args); checkResult(result); } - private static void compile(ResolvedJavaMethod method, int bci) { + protected static void compile(OptionValues options, ResolvedJavaMethod method, int bci) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); long jvmciEnv = 0L; HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, bci, jvmciEnv); HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); - CompilationTask task = new CompilationTask(runtime, compiler, request, true, true); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, options); HotSpotCompilationRequestResult result = task.runCompilation(); if (result.getFailure() != null) { throw new GraalError(result.getFailureMessage()); @@ -79,19 +87,24 @@ public abstract class GraalOSRTestBase extends GraalCompilerTest { private static int getBackedgeBCI(ResolvedJavaMethod method) { Bytecode code = new ResolvedJavaMethodBytecode(method); BytecodeStream stream = new BytecodeStream(code.getCode()); - BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code); - assert bciBlockMapping.getLoopCount() == 1 : "Expected exactly one loop " + method; + BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code, getInitialOptions()); for (BciBlock block : bciBlockMapping.getBlocks()) { - int bci = block.startBci; - for (BciBlock succ : block.getSuccessors()) { - int succBci = succ.startBci; - if (succBci < bci) { - // back edge - return succBci; + if (block.startBci != -1) { + int bci = block.startBci; + for (BciBlock succ : block.getSuccessors()) { + if (succ.startBci != -1) { + int succBci = succ.startBci; + if (succBci < bci) { + // back edge + return succBci; + } + } } } } + TTY.println("Cannot find loop back edge with bytecode loops at:%s", Arrays.toString(bciBlockMapping.getLoopHeaders())); + TTY.println(new BytecodeDisassembler().disassemble(code)); return -1; } @@ -102,17 +115,20 @@ public abstract class GraalOSRTestBase extends GraalCompilerTest { Assert.assertEquals(ReturnValue.SUCCESS, result.returnValue); } - private void compileOSR(ResolvedJavaMethod method) { + private void compileOSR(OptionValues options, ResolvedJavaMethod method) { + // ensure eager resolving + parseEager(method, AllowAssumptions.YES, options); int bci = getBackedgeBCI(method); assert bci != -1; // ensure eager resolving - parseEager(method, AllowAssumptions.YES); - compile(method, bci); + parseEager(method, AllowAssumptions.YES, options); + compile(options, method, bci); } protected enum ReturnValue { SUCCESS, - FAILURE + FAILURE, + SIDE } public GraalOSRTestBase() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java index 1851b2619ea..acf2668f571 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java @@ -54,9 +54,9 @@ public abstract class HotSpotGraalCompilerTest extends GraalCompilerTest { HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); HotSpotProviders providers = rt.getHostBackend().getProviders(); CompilationIdentifier compilationId = runtime().getHostBackend().getCompilationIdentifier(method); - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId, getInitialOptions()); if (graph != null) { - return getCode(method, graph, true, true); + return getCode(method, graph, true, true, graph.getOptions()); } return null; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java new file mode 100644 index 00000000000..0cb656cd88c --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java @@ -0,0 +1,705 @@ +/* + * 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 java.lang.annotation.Annotation; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +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 jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.ExceptionHandler; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.LineNumberTable; +import jdk.vm.ci.meta.LocalVariableTable; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; +import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalMBean; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +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 org.junit.Test; + +public class HotSpotGraalMBeanTest { + @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 = 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 MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) { + MBeanAttributeInfo printCompilation = null; + for (MBeanAttributeInfo attr : 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 = 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 = 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 OptionValues forMethod = realBean.optionsFor(unsetDump, new MockResolvedJavaMethod()); + assertNotSame(unsetDump, forMethod); + Object nothing = unsetDump.getMap().get(GraalDebugConfig.Options.Dump); + assertEquals("Empty string", "", nothing); + + Object specialValue = forMethod.getMap().get(GraalDebugConfig.Options.Dump); + assertEquals(":3", specialValue); + + OptionValues normalMethod = realBean.optionsFor(unsetDump, null); + Object noSpecialValue = normalMethod.getMap().get(GraalDebugConfig.Options.Dump); + assertEquals("Empty string", "", noSpecialValue); + } + + private static class MockResolvedJavaMethod implements HotSpotResolvedJavaMethod { + MockResolvedJavaMethod() { + } + + @Override + public boolean isCallerSensitive() { + throw new UnsupportedOperationException(); + } + + @Override + public HotSpotResolvedObjectType getDeclaringClass() { + return new MockResolvedObjectType(); + } + + @Override + public boolean isForceInline() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasReservedStackAccess() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNotInlineable() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean ignoredBySecurityStackWalk() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasCompiledCode() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasCompiledCodeAtLevel(int level) { + throw new UnsupportedOperationException(); + } + + @Override + public int vtableEntryOffset(ResolvedJavaType resolved) { + throw new UnsupportedOperationException(); + } + + @Override + public int intrinsicId() { + throw new UnsupportedOperationException(); + } + + @Override + public int allocateCompileId(int entryBCI) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasCodeAtLevel(int entryBCI, int level) { + throw new UnsupportedOperationException(); + } + + @Override + public byte[] getCode() { + throw new UnsupportedOperationException(); + } + + @Override + public int getCodeSize() { + throw new UnsupportedOperationException(); + } + + @Override + public int getMaxLocals() { + throw new UnsupportedOperationException(); + } + + @Override + public int getMaxStackSize() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSynthetic() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isVarArgs() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isBridge() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isClassInitializer() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isConstructor() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean canBeStaticallyBound() { + throw new UnsupportedOperationException(); + } + + @Override + public ExceptionHandler[] getExceptionHandlers() { + throw new UnsupportedOperationException(); + } + + @Override + public StackTraceElement asStackTraceElement(int bci) { + throw new UnsupportedOperationException(); + } + + @Override + public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) { + throw new UnsupportedOperationException(); + } + + @Override + public void reprofile() { + throw new UnsupportedOperationException(); + } + + @Override + public ConstantPool getConstantPool() { + throw new UnsupportedOperationException(); + } + + @Override + public Annotation[][] getParameterAnnotations() { + throw new UnsupportedOperationException(); + } + + @Override + public Type[] getGenericParameterTypes() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean canBeInlined() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasNeverInlineDirective() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean shouldBeInlined() { + throw new UnsupportedOperationException(); + } + + @Override + public LineNumberTable getLineNumberTable() { + throw new UnsupportedOperationException(); + } + + @Override + public LocalVariableTable getLocalVariableTable() { + throw new UnsupportedOperationException(); + } + + @Override + public Constant getEncoding() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isInVirtualMethodTable(ResolvedJavaType resolved) { + throw new UnsupportedOperationException(); + } + + @Override + public SpeculationLog getSpeculationLog() { + throw new UnsupportedOperationException(); + } + + @Override + public String getName() { + return "asList"; + } + + @Override + public Signature getSignature() { + throw new UnsupportedOperationException(); + } + + @Override + public int getModifiers() { + throw new UnsupportedOperationException(); + } + + @Override + public T getAnnotation(Class annotationClass) { + throw new UnsupportedOperationException(); + } + + @Override + public Annotation[] getAnnotations() { + throw new UnsupportedOperationException(); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isIntrinsicCandidate() { + return true; + } + + private static class MockResolvedObjectType implements HotSpotResolvedObjectType { + MockResolvedObjectType() { + } + + @Override + public long getFingerprint() { + return 0L; + } + + @Override + public HotSpotResolvedObjectType getArrayClass() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaType getComponentType() { + throw new UnsupportedOperationException(); + } + + @Override + public Assumptions.AssumptionResult findLeafConcreteSubtype() { + throw new UnsupportedOperationException(); + } + + @Override + public HotSpotResolvedObjectType getSuperclass() { + throw new UnsupportedOperationException(); + } + + @Override + public HotSpotResolvedObjectType[] getInterfaces() { + throw new UnsupportedOperationException(); + } + + @Override + public HotSpotResolvedObjectType getSupertype() { + throw new UnsupportedOperationException(); + } + + @Override + public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) { + throw new UnsupportedOperationException(); + } + + @Override + public ConstantPool getConstantPool() { + throw new UnsupportedOperationException(); + } + + @Override + public int instanceSize() { + throw new UnsupportedOperationException(); + } + + @Override + public int getVtableLength() { + throw new UnsupportedOperationException(); + } + + @Override + public Assumptions.AssumptionResult findUniqueConcreteMethod(ResolvedJavaMethod method) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) { + throw new UnsupportedOperationException(); + } + + @Override + public Constant klass() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isPrimaryType() { + throw new UnsupportedOperationException(); + } + + @Override + public int superCheckOffset() { + throw new UnsupportedOperationException(); + } + + @Override + public long prototypeMarkWord() { + throw new UnsupportedOperationException(); + } + + @Override + public int layoutHelper() { + throw new UnsupportedOperationException(); + } + + @Override + public HotSpotResolvedObjectType getEnclosingType() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaMethod getClassInitializer() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasFinalizer() { + throw new UnsupportedOperationException(); + } + + @Override + public Assumptions.AssumptionResult hasFinalizableSubclass() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isInterface() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isInstanceClass() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isInitialized() { + throw new UnsupportedOperationException(); + } + + @Override + public void initialize() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isLinked() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isAssignableFrom(ResolvedJavaType other) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isInstance(JavaConstant obj) { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaType getSingleImplementor() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaField[] getStaticFields() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind) { + throw new UnsupportedOperationException(); + } + + @Override + public String getSourceFileName() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isLocal() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isMember() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaMethod[] getDeclaredConstructors() { + throw new UnsupportedOperationException(); + } + + @Override + public ResolvedJavaMethod[] getDeclaredMethods() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isCloneableWithAllocation() { + throw new UnsupportedOperationException(); + } + + @Override + public String getName() { + return "Ljava/util/Arrays;"; + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + throw new UnsupportedOperationException(); + } + + @Override + public int getModifiers() { + throw new UnsupportedOperationException(); + } + + @Override + public T getAnnotation(Class annotationClass) { + throw new UnsupportedOperationException(); + } + + @Override + public Annotation[] getAnnotations() { + throw new UnsupportedOperationException(); + } + + @Override + public Annotation[] getDeclaredAnnotations() { + throw new UnsupportedOperationException(); + } + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java index fe000286b9b..384f84886ee 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Test; import org.graalvm.compiler.graph.Node; @@ -40,7 +38,7 @@ public class HotSpotNodeSubstitutionsTest extends MethodSubstitutionTest { @Test public void test() { - StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions(), AllowAssumptions.YES).build(); test("getNodeClass", ConstantNode.forInt(42, graph)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java index 549a69b238d..1265cd91f7f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java @@ -36,7 +36,7 @@ import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; - +import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; @@ -52,18 +52,24 @@ public class HotSpotResolvedJavaFieldTest extends HotSpotGraalCompilerTest { private static final Class[] classesWithInternalFields = {Class.class, ClassLoader.class}; private static final Method createFieldMethod; + private static final Field indexField; static { - Method ret = null; + Method m = null; + Field f = null; try { Class typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl"); - ret = typeImpl.getDeclaredMethod("createField", String.class, JavaType.class, long.class, int.class); - ret.setAccessible(true); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { - e.printStackTrace(); + m = typeImpl.getDeclaredMethod("createField", JavaType.class, long.class, int.class, int.class); + Util.setAccessible(m, true); + Class fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl"); + f = fieldImpl.getDeclaredField("index"); + Util.setAccessible(f, true); + } catch (Exception e) { + throw new AssertionError(e); } - createFieldMethod = ret; + createFieldMethod = m; + indexField = f; } /** @@ -96,21 +102,22 @@ public class HotSpotResolvedJavaFieldTest extends HotSpotGraalCompilerTest { /** * Tests that {@code HotSpotResolvedObjectType#createField(String, JavaType, long, int)} always - * returns the same object for an internal field. + * returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an internal + * field. * * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ @Test - public void testCachingForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Assert.assertTrue("HotSpotResolvedObjectTypeImpl.createField method not found", createFieldMethod != null); + public void testEquivalenceForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { for (Class c : classesWithInternalFields) { HotSpotResolvedObjectType type = HotSpotResolvedObjectType.fromObjectClass(c); for (ResolvedJavaField field : type.getInstanceFields(false)) { if (field.isInternal()) { HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field; - ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getName(), expected.getType(), expected.offset(), expected.getModifiers()); + int index = indexField.getInt(expected); + ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.offset(), expected.getModifiers(), index); Assert.assertEquals(expected, actual); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java new file mode 100644 index 00000000000..74bfeaa3b9e --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java @@ -0,0 +1,51 @@ +/* + * 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.test; + +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.core.common.type.ObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; +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; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MemoryAccessProvider; + +public class HotSpotStampMemoryAccessTest extends HotSpotGraalCompilerTest { + + @Ignore("not all versions are safe yet") + @Test + public void testReadNarrowObject() { + CompressEncoding oopEncoding = runtime().getVMConfig().getOopEncoding(); + Assume.assumeTrue("Compressed oops must be enabled", runtime().getVMConfig().useCompressedOops); + MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider(); + JavaConstant base = getSnippetReflection().forObject(""); + ObjectStamp stamp = (ObjectStamp) StampFactory.forKind(JavaKind.Object); + Stamp narrowStamp = HotSpotNarrowOopStamp.compressed(stamp, oopEncoding); + assertTrue(narrowStamp.readConstant(memory, base, 128) == null); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java index 9d9e1598bec..3717e9dcc14 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java @@ -24,15 +24,15 @@ package org.graalvm.compiler.hotspot.test; import static java.lang.reflect.Modifier.isStatic; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -76,8 +76,8 @@ public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java index 65676eff909..837ad0e7cb7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java @@ -53,6 +53,7 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.VirtualObject; import jdk.vm.ci.code.site.InfopointReason; import jdk.vm.ci.common.JVMCIError; @@ -140,8 +141,9 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest { graph.addAfterFixed(graph.start(), test); CompilationResult compResult = compile(method, graph); - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(method, null, compResult); - getCodeCache().addCode(method, compiledCode, null, null); + CodeCacheProvider codeCache = getCodeCache(); + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, method, null, compResult); + codeCache.addCode(method, compiledCode, null, null); } @Test(expected = JVMCIError.class) diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java index 57c9776498d..bb968a964b8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java @@ -30,8 +30,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.meta.JavaKind; @@ -58,10 +57,12 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected Suites createSuites() { - try (OverrideScope s = OptionValue.override(GraalOptions.ImmutableCode, true)) { - return super.createSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(getOptions()); + } + + private static OptionValues getOptions() { + return new OptionValues(getInitialOptions(), GraalOptions.ImmutableCode, true); } @Override @@ -80,7 +81,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testClassConstant() { - test("classConstant"); + test(getOptions(), "classConstant"); } public static Class primitiveClassConstant() { @@ -89,7 +90,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testPrimitiveClassConstant() { - test("primitiveClassConstant"); + test(getOptions(), "primitiveClassConstant"); } public static Wrapper compressedClassConstant(Wrapper w) { @@ -100,7 +101,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testCompressedClassConstant() { ArgSupplier arg = () -> new Wrapper(); - test("compressedClassConstant", arg); + test(getOptions(), "compressedClassConstant", arg); } public static Wrapper compressedPrimitiveClassConstant(Wrapper w) { @@ -111,6 +112,6 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testCompressedPrimitiveClassConstant() { ArgSupplier arg = () -> new Wrapper(); - test("compressedPrimitiveClassConstant", arg); + test(getOptions(), "compressedPrimitiveClassConstant", arg); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java index f12b0ba0a4e..73bf573360c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java @@ -26,14 +26,11 @@ import static org.graalvm.compiler.debug.internal.MemUseTrackerImpl.getCurrentTh import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.AllocSpy; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.hotspot.CompilationTask; -import org.graalvm.compiler.hotspot.CompileTheWorld; -import org.graalvm.compiler.hotspot.CompileTheWorldOptions; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -53,7 +50,7 @@ import jdk.vm.ci.runtime.JVMCICompiler; * Memory analysis for a {@link CompileTheWorld} execution can also be performed. For example: * *
    - *     mx --vm server vm -XX:-UseJVMCIClassLoader -Dgraal.CompileTheWorldClasspath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @org.graalvm.compiler.hotspot.test org.graalvm.compiler.hotspot.test.MemoryUsageBenchmark
    + *     mx vm -XX:-UseJVMCIClassLoader -DCompileTheWorld.Classpath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @org.graalvm.compiler.hotspot.test org.graalvm.compiler.hotspot.test.MemoryUsageBenchmark
      * 
    */ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { @@ -125,9 +122,7 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { Graal.getRuntime(); // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(System.out); - } + DebugEnvironment.ensureInitialized(getInitialOptions()); new MemoryUsageBenchmark().run(); } @@ -144,7 +139,7 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false); + CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions()); task.runCompilation(); } } @@ -161,7 +156,7 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { try (AllocSpy as = AllocSpy.open(methodName)) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false); + CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions()); task.runCompilation(); } } @@ -185,9 +180,10 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { public void run() { compileAndTime("simple"); compileAndTime("complex"); - if (CompileTheWorldOptions.CompileTheWorldClasspath.getValue() != CompileTheWorld.SUN_BOOT_CLASS_PATH) { + OptionValues options = CompileTheWorld.loadOptions(getInitialOptions()); + if (CompileTheWorld.Options.Classpath.getValue(options) != CompileTheWorld.SUN_BOOT_CLASS_PATH) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); - CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler()); + CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), options); try { ctw.compile(); } catch (Throwable e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectCloneTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectCloneTest.java new file mode 100644 index 00000000000..02baa30a806 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectCloneTest.java @@ -0,0 +1,87 @@ +/* + * 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.test; + +import java.util.ArrayList; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.junit.Test; + +/** + * Exercise intrinsification of {@link Object#clone}. + */ +public class ObjectCloneTest extends GraalCompilerTest { + + public static Object cloneArray(int[] array) { + return array.clone(); + } + + public static Object cloneList(ArrayList list) { + return list.clone(); + } + + static class ObjectCloneable implements Cloneable { + int field; + + @Override + protected Object clone() throws CloneNotSupportedException { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + } + + static class CloneableSubclass extends ObjectCloneable { + + } + + /* + * This test checks that the ObjectCloneNode doesn't accidentally inject non-nullness into the + * graph which is later removed. + */ + public static Object notCloneable(ObjectCloneable cloneable) throws CloneNotSupportedException { + ObjectCloneable clone = (ObjectCloneable) cloneable.clone(); + return clone.getClass(); + } + + @Test + public void testNotIntrinsified() throws Throwable { + test("notCloneable", new CloneableSubclass()); + } + + @Test + public void testArray() throws Throwable { + test("cloneArray", new int[]{1, 2, 4, 3}); + } + + @Test + public void testList() throws Throwable { + ArrayList list = new ArrayList<>(); + for (int i = 0; i < 4; i++) { + list.add(i); + } + test("cloneList", list); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java new file mode 100644 index 00000000000..a02045810c8 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.debug.GraalDebugConfig.Options.Dump; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraph; +import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; +import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.List; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.test.SubprocessUtil; +import org.graalvm.compiler.test.SubprocessUtil.Subprocess; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests reading options from a file specified by the {@code graal.options.file}. + */ +public class OptionsInFileTest extends GraalCompilerTest { + @Test + public void test() throws IOException, InterruptedException { + String methodFilterValue = "a very unlikely method name"; + String debugFilterValue = "a very unlikely debug scope"; + File optionsFile = File.createTempFile("options", ".properties").getAbsoluteFile(); + try { + Assert.assertFalse(methodFilterValue.equals(MethodFilter.getDefaultValue())); + Assert.assertFalse(debugFilterValue.equals(Dump.getDefaultValue())); + Assert.assertTrue(PrintGraph.getDefaultValue()); + + try (PrintStream out = new PrintStream(new FileOutputStream(optionsFile))) { + out.println(MethodFilter.getName() + "=" + methodFilterValue); + out.println(Dump.getName() + "=" + debugFilterValue); + out.println(PrintGraph.getName() + " = false"); + } + + List vmArgs = withoutDebuggerArguments(getVMCommandLine()); + vmArgs.removeIf(a -> a.startsWith("-Dgraal.")); + vmArgs.add("-Dgraal.options.file=" + optionsFile); + vmArgs.add("-XX:+JVMCIPrintProperties"); + Subprocess proc = SubprocessUtil.java(vmArgs); + String[] expected = { + "graal.MethodFilter := \"a very unlikely method name\"", + "graal.Dump := \"a very unlikely debug scope\"", + "graal.PrintGraph := false"}; + for (String line : proc.output) { + for (int i = 0; i < expected.length; i++) { + if (expected[i] != null && line.contains(expected[i])) { + expected[i] = null; + } + } + } + + for (int i = 0; i < expected.length; i++) { + if (expected[i] != null) { + Assert.fail(String.format("Did not find '%s' in output of command:%n%s", expected[i], proc)); + } + } + } finally { + optionsFile.delete(); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java new file mode 100644 index 00000000000..06d12bc8733 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java @@ -0,0 +1,162 @@ +/* + * 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.test; + +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; +import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; +import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; +import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; +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.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; + +public class ReplaceConstantNodesPhaseTest extends HotSpotGraalCompilerTest { + private final GraalHotSpotVMConfig config = runtime().getVMConfig(); + + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins plugins = super.getDefaultGraphBuilderPlugins(); + plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); + return plugins; + } + + public static class X { + public static int x; + public static int y; + public static int z; + public static Object o; + } + + public static class Y extends X { + public static int a; + public static int b; + } + + public static int a; + + public static void assignFields() { + X.x = 1; + X.y = 2; + X.z = 3; + } + + public static void assignFieldsInBranches(boolean x) { + if (x) { + X.y = 1; + } else { + X.z = 2; + } + } + + public static void assignFieldsWithDominatingInit(boolean x) { + X.x = 1; + if (x) { + X.y = 2; + } else { + X.z = 3; + } + } + + public static void assignString() { + X.o = "foo"; + } + + public static void assignToParentAndChild() { + Y.a = 1; + X.x = 2; + } + + public static void assignToThis() { + a = 1; + } + + public static void assignFieldsWithDominatingInitOfParent(boolean x) { + Y.a = 1; + if (x) { + X.y = 2; + } else { + X.z = 3; + } + Y.b = 4; + } + + private void test(String name, int expectedInits, int expectedResolves, int expectedLoads) { + StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true)); + HighTierContext highTierContext = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + new EliminateRedundantInitializationPhase().apply(graph, highTierContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); + new LoadJavaMirrorWithKlassPhase(config).apply(graph, highTierContext); + new ReplaceConstantNodesPhase(false).apply(graph, highTierContext); + Assert.assertEquals(expectedInits, graph.getNodes().filter(InitializeKlassNode.class).count()); + Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveConstantNode.class).count()); + Assert.assertEquals(expectedLoads, graph.getNodes().filter(LoadConstantIndirectlyNode.class).count()); + } + + @Test + public void test1() { + test("assignFields", 1, 0, 0); + } + + @Test + public void test2() { + test("assignFieldsWithDominatingInit", 1, 0, 0); + } + + @Test + public void test3() { + test("assignString", 1, 1, 0); + } + + @Test + public void test4() { + test("assignToParentAndChild", 1, 1, 0); + } + + @Test + public void test5() { + test("assignToThis", 0, 0, 1); + } + + @Test + public void test6() { + test("assignFieldsWithDominatingInitOfParent", 1, 1, 0); + } + + @Test + public void test7() { + test("assignFieldsInBranches", 2, 1, 0); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java new file mode 100644 index 00000000000..1fe978293bf --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.test.SubprocessUtil.getVMCommandLine; +import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.test.SubprocessUtil; +import org.graalvm.compiler.test.SubprocessUtil.Subprocess; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests support for dumping graphs and other info useful for debugging a compiler crash. + */ +public class RetryableCompilationTest extends GraalCompilerTest { + + /** + * Tests compilation requested by the VM. + */ + @Test + public void testVMCompilation() throws IOException, InterruptedException { + testHelper(Arrays.asList("-XX:+BootstrapJVMCI", "-XX:+UseJVMCICompiler", "-Dgraal.CrashAt=Object.*,String.*", "-version")); + } + + /** + * Tests compilation requested by Truffle. + */ + @Test + public void testTruffleCompilation() throws IOException, InterruptedException { + testHelper(Arrays.asList("-Dgraal.CrashAt=root test1"), "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test"); + } + + private static void testHelper(List extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException { + List vmArgs = withoutDebuggerArguments(getVMCommandLine()); + vmArgs.removeIf(a -> a.startsWith("-Dgraal.")); + // Force output to a file even if there's a running IGV instance available. + vmArgs.add("-Dgraal.PrintGraphFile=true"); + vmArgs.addAll(extraVmArgs); + + Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs); + + String forcedCrashString = "Forced crash after compiling"; + String diagnosticOutputFilePrefix = "Graal diagnostic output saved in "; + + boolean seenForcedCrashString = false; + String diagnosticOutputZip = null; + + for (String line : proc.output) { + if (line.contains(forcedCrashString)) { + seenForcedCrashString = true; + } else if (diagnosticOutputZip == null) { + int index = line.indexOf(diagnosticOutputFilePrefix); + if (index != -1) { + diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim(); + } + } + } + if (!seenForcedCrashString) { + Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, proc)); + } + if (diagnosticOutputZip == null) { + Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, proc)); + } + + File zip = new File(diagnosticOutputZip).getAbsoluteFile(); + Assert.assertTrue(zip.toString(), zip.exists()); + try { + int bgv = 0; + int cfg = 0; + ZipFile dd = new ZipFile(diagnosticOutputZip); + List entries = new ArrayList<>(); + for (Enumeration e = dd.entries(); e.hasMoreElements();) { + ZipEntry ze = e.nextElement(); + String name = ze.getName(); + entries.add(name); + if (name.endsWith(".bgv")) { + bgv++; + } else if (name.endsWith(".cfg")) { + cfg++; + } + } + if (bgv == 0) { + Assert.fail(String.format("Expected at least one .bgv file in %s: %s", diagnosticOutputZip, entries)); + } + if (cfg == 0) { + Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries)); + } + } finally { + zip.delete(); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java index 0333f9a973f..f79787dce30 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java @@ -25,7 +25,6 @@ package org.graalvm.compiler.hotspot.test; import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; import java.util.List; -import java.util.Map; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.GraalCompilerTest; @@ -39,6 +38,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.util.EconomicMap; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; @@ -60,7 +60,7 @@ public class TestIntrinsicCompiles extends GraalCompilerTest { Plugins graphBuilderPlugins = providers.getGraphBuilderPlugins(); InvocationPlugins invocationPlugins = graphBuilderPlugins.getInvocationPlugins(); - Map> bindings = invocationPlugins.getBindings(true); + EconomicMap> bindings = invocationPlugins.getBindings(true); HotSpotVMConfigStore store = rt.getVMConfig().getStore(); List intrinsics = store.getIntrinsics(); for (VMIntrinsicMethod intrinsic : intrinsics) { @@ -69,7 +69,7 @@ public class TestIntrinsicCompiles extends GraalCompilerTest { if (plugin instanceof MethodSubstitutionPlugin) { ResolvedJavaMethod method = CheckGraalIntrinsics.resolveIntrinsic(getMetaAccess(), intrinsic); if (!method.isNative()) { - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID, getInitialOptions()); getCode(method, graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java index 14ab256a2fa..1349e8ec50d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java @@ -266,7 +266,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest { new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new WriteBarrierAdditionPhase(config).apply(graph); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After Write Barrier Addition"); + Debug.dump(Debug.BASIC_LEVEL, graph, "After Write Barrier Addition"); int barriers = 0; if (config.useG1GC) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java index ce367b0831e..b3c9fc44b56 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java @@ -23,12 +23,8 @@ package org.graalvm.compiler.hotspot.test; import java.util.List; -import java.util.Map; - import org.junit.Assert; import org.junit.Test; - -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugConfig; @@ -66,6 +62,8 @@ import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.graalvm.util.EconomicMap; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.ResolvedJavaField; @@ -306,7 +304,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { test("test6Snippet", 5, new int[]{1, 2}); } - @Test(expected = AssertionError.class) + @Test public void test23() { test("test6Snippet", 5, new int[]{3}); } @@ -712,7 +710,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { } @Override - protected Map processLoop(LoopBeginNode loop, Boolean initialState) { + protected EconomicMap processLoop(LoopBeginNode loop, Boolean initialState) { return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; } @@ -729,7 +727,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { DebugConfig debugConfig = DebugScope.getConfig(); DebugConfig fixedConfig = debugConfig == null ? null - : Debug.fixedConfig(0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); + : Debug.fixedConfig(debugConfig.getOptions(), 0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { ReentrantNodeIterator.apply(closure, graph.start(), false); new WriteBarrierVerificationPhase(config).apply(graph); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java index 3a93d463936..cec7868e3c7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot; +import org.graalvm.compiler.core.common.CompressEncoding; + import jdk.vm.ci.hotspot.HotSpotVMConfigStore; public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { @@ -30,11 +32,15 @@ public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) { super(store); - // In AOT, force the shift to be always equal to alignment therefore avoiding zero-shift. + // AOT captures VM settings during compilation. For compressed oops this + // presents a problem for the case when the VM selects a zero-shift mode + // (i.e., when the heap is less than 4G). Compiling an AOT binary with + // zero-shift limits its usability. As such we force the shift to be + // always equal to alignment to avoid emitting zero-shift AOT code. CompressEncoding vmOopEncoding = super.getOopEncoding(); - aotOopEncoding = new CompressEncoding(vmOopEncoding.base, vmOopEncoding.alignment, vmOopEncoding.alignment); + aotOopEncoding = new CompressEncoding(vmOopEncoding.getBase(), logMinObjAlignment()); CompressEncoding vmKlassEncoding = super.getKlassEncoding(); - aotKlassEncoding = new CompressEncoding(vmKlassEncoding.base, vmKlassEncoding.alignment, vmKlassEncoding.alignment); + aotKlassEncoding = new CompressEncoding(vmKlassEncoding.getBase(), logKlassAlignment); assert check(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java index 7e4ac5fe897..2fc58b3e698 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt; -import static org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory.GRAAL_OPTION_PROPERTY_PREFIX; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; import java.util.Arrays; import java.util.HashMap; @@ -32,8 +32,9 @@ import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CompilationRequest; @@ -58,9 +59,9 @@ final class BootstrapWatchDog extends Thread { // @formatter:off @Option(help = "Ratio of the maximum compilation rate below which the bootstrap compilation rate must not fall " + "(0 or less disables monitoring).", type = OptionType.Debug) - public static final OptionValue BootstrapWatchDogCriticalRateRatio = new OptionValue<>(0.25D); + public static final OptionKey BootstrapWatchDogCriticalRateRatio = new OptionKey<>(0.25D); @Option(help = "Maximum time in minutes to spend bootstrapping (0 to disable this limit).", type = OptionType.Debug) - public static final OptionValue BootstrapTimeout = new OptionValue<>(15D); + public static final OptionKey BootstrapTimeout = new OptionKey<>(15D); // @formatter:on } @@ -88,13 +89,18 @@ final class BootstrapWatchDog extends Thread { * {@code null}. */ static BootstrapWatchDog maybeCreate(HotSpotGraalRuntimeProvider graalRuntime) { - return MAX_RATE_DECREASE <= 0.0D && TIMEOUT == 0 ? null : new BootstrapWatchDog(graalRuntime); + OptionValues options = graalRuntime.getOptions(); + int timeout = (int) (Options.BootstrapTimeout.getValue(options) * 60); + double maxRateDecrease = Options.BootstrapWatchDogCriticalRateRatio.getValue(options); + return maxRateDecrease <= 0.0D && timeout == 0 ? null : new BootstrapWatchDog(graalRuntime, timeout, maxRateDecrease); } - private BootstrapWatchDog(HotSpotGraalRuntimeProvider graalRuntime) { + private BootstrapWatchDog(HotSpotGraalRuntimeProvider graalRuntime, int timeout, double maxRateDecrease) { this.setName(getClass().getSimpleName()); this.start(); this.graalRuntime = graalRuntime; + this.timeout = timeout; + this.maxRateDecrease = maxRateDecrease; } /** @@ -115,13 +121,13 @@ final class BootstrapWatchDog extends Thread { /** * Time in seconds before stopping a bootstrap. */ - private static final int TIMEOUT = (int) (Options.BootstrapTimeout.getValue() * 60); + private final int timeout; /** * The watch dog {@link #hitCriticalCompilationRateOrTimeout() hits} a critical compilation rate * if the current compilation rate falls below this ratio of the maximum compilation rate. */ - private static final double MAX_RATE_DECREASE = Options.BootstrapWatchDogCriticalRateRatio.getValue(); + private final double maxRateDecrease; @Override public void run() { @@ -142,16 +148,16 @@ final class BootstrapWatchDog extends Thread { } if (rate > maxRate) { maxRate = rate; - } else if (rate < (maxRate * MAX_RATE_DECREASE)) { + } else if (rate < (maxRate * maxRateDecrease)) { TTY.printf("%nAfter %.2f seconds bootstrapping, compilation rate is %.2f compilations per second " + - "which is below %.2f times the max compilation rate of %.2f%n", seconds(elapsed), rate, MAX_RATE_DECREASE, maxRate); + "which is below %.2f times the max compilation rate of %.2f%n", seconds(elapsed), rate, maxRateDecrease, maxRate); TTY.printf("To enable monitoring of long running individual compilations, re-run with -D%s%s=%.2f%n", GRAAL_OPTION_PROPERTY_PREFIX, CompilationWatchDog.Options.CompilationWatchDogStartDelay.getName(), seconds(elapsed) - 5); hitCriticalRateOrTimeout = true; return; } - if (elapsed > TIMEOUT * 1000) { + if (elapsed > timeout * 1000) { if (requestsAtTimeout == null) { requestsAtTimeout = snapshotRequests(); stacksAtTimeout = new HashMap<>(); @@ -205,7 +211,7 @@ final class BootstrapWatchDog extends Thread { } /** - * Queries whether a critically low compilation rate or {@link #TIMEOUT} occurred. + * Queries whether a critically low compilation rate or {@link #timeout} occurred. */ boolean hitCriticalCompilationRateOrTimeout() { return hitCriticalRateOrTimeout; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java index e5f0f4ecc4c..824641be1b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java @@ -24,7 +24,6 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.str; - import java.util.Comparator; import java.util.HashMap; import java.util.Map; @@ -35,9 +34,8 @@ import java.util.TreeSet; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; - +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -47,12 +45,15 @@ class CompilationCounters { // @formatter:off @Option(help = "The number of compilations allowed for any method before " + "the VM exits (a value of 0 means there is no limit).", type = OptionType.Debug) - public static final OptionValue CompilationCountLimit = new StableOptionValue<>(0); + public static final OptionKey CompilationCountLimit = new OptionKey<>(0); // @formatter:on } - CompilationCounters() { + private final OptionValues options; + + CompilationCounters(OptionValues options) { TTY.println("Warning: Compilation counters enabled, excessive recompilation of a method will cause a failure!"); + this.options = options; } private final Map counters = new HashMap<>(); @@ -68,16 +69,16 @@ class CompilationCounters { Integer val = counters.get(method); val = val != null ? val + 1 : 1; counters.put(method, val); - if (val > Options.CompilationCountLimit.getValue()) { + if (val > Options.CompilationCountLimit.getValue(options)) { TTY.printf("Error. Method %s was compiled too many times. Number of compilations: %d\n", fmt(method), - CompilationCounters.Options.CompilationCountLimit.getValue()); + CompilationCounters.Options.CompilationCountLimit.getValue(options)); TTY.println("==================================== High compilation counters ===================================="); SortedSet> sortedCounters = new TreeSet<>(new CounterComparator()); for (Map.Entry e : counters.entrySet()) { sortedCounters.add(e); } for (Map.Entry entry : sortedCounters) { - if (entry.getValue() >= Options.CompilationCountLimit.getValue() / 2) { + if (entry.getValue() >= Options.CompilationCountLimit.getValue(options) / 2) { TTY.out.printf("%d\t%s%n", entry.getValue(), str(entry.getKey())); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java index a40d0711aaf..b0bcd702324 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java @@ -44,7 +44,8 @@ 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.OptionValue; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import com.sun.management.ThreadMXBean; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -56,12 +57,11 @@ public final class CompilationStatistics { public static class Options { // @formatter:off @Option(help = "Enables CompilationStatistics.") - public static final OptionValue UseCompilationStatistics = new OptionValue<>(false); + public static final OptionKey UseCompilationStatistics = new OptionKey<>(false); // @formatter:on } private static final long RESOLUTION = 100000000; - private static final boolean ENABLED = Options.UseCompilationStatistics.getValue(); private static final CompilationStatistics DUMMY = new CompilationStatistics(null, false); @@ -114,6 +114,7 @@ public final class CompilationStatistics { bytecodeCount = method.getCodeSize(); threadAllocatedBytesStart = getThreadAllocatedBytes(); } else { + assert DUMMY == null : "only DUMMY has no method"; holder = ""; name = ""; signature = ""; @@ -122,7 +123,7 @@ public final class CompilationStatistics { } public void finish(HotSpotResolvedJavaMethod method, HotSpotInstalledCode code) { - if (ENABLED) { + if (isEnabled()) { duration = System.nanoTime() - startTime; codeSize = (int) code.getCodeSize(); memoryUsed = getThreadAllocatedBytes() - threadAllocatedBytesStart; @@ -137,8 +138,8 @@ public final class CompilationStatistics { return current.get().isEmpty() ? null : current.get().getLast(); } - public static CompilationStatistics create(HotSpotResolvedJavaMethod method, boolean isOSR) { - if (ENABLED) { + public static CompilationStatistics create(OptionValues options, HotSpotResolvedJavaMethod method, boolean isOSR) { + if (Options.UseCompilationStatistics.getValue(options)) { CompilationStatistics stats = new CompilationStatistics(method, isOSR); list.add(stats); current.get().addLast(stats); @@ -148,11 +149,12 @@ public final class CompilationStatistics { } } + public boolean isEnabled() { + return this != DUMMY; + } + @SuppressWarnings("deprecation") public static void clear(String dumpName) { - if (!ENABLED) { - return; - } try { ConcurrentLinkedDeque snapshot = list; long snapshotZeroTime = zeroTime; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java index e86a1bdb71c..5948a0205fe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java @@ -30,6 +30,7 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter; import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; +import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; import java.util.List; @@ -44,15 +45,15 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TimeSource; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.EventProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; -import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotInstalledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; import jdk.vm.ci.hotspot.HotSpotNmethod; @@ -60,8 +61,6 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.services.JVMCIServiceLocator; -//JaCoCo Exclude - public class CompilationTask { private static final DebugCounter BAILOUTS = Debug.counter("Bailouts"); @@ -93,6 +92,91 @@ public class CompilationTask { private final boolean installAsDefault; private final boolean useProfilingInfo; + private final OptionValues options; + + final class RetryableCompilation extends HotSpotRetryableCompilation { + private final EventProvider.CompilationEvent compilationEvent; + CompilationResult result; + + RetryableCompilation(EventProvider.CompilationEvent compilationEvent) { + super(compiler.getGraalRuntime(), options); + this.compilationEvent = compilationEvent; + } + + @Override + public String toString() { + return getMethod().format("%H.%n"); + } + + @SuppressWarnings("try") + @Override + protected HotSpotCompilationRequestResult run(Throwable retryCause) { + HotSpotResolvedJavaMethod method = getMethod(); + int entryBCI = getEntryBCI(); + final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); + final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed(); + final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed(); + if (printCompilation) { + TTY.println(getMethodDescription() + "..."); + } + + TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method); + final long start; + final long allocatedBytesBefore; + if (printAfterCompilation || printCompilation) { + final long threadId = Thread.currentThread().getId(); + start = TimeSource.getTimeNS(); + allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L; + } else { + start = 0L; + allocatedBytesBefore = 0L; + } + + try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { + // Begin the compilation event. + compilationEvent.begin(); + result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options); + } catch (Throwable e) { + if (retryCause != null) { + log("Exception during retry", e); + } + throw Debug.handle(e); + } finally { + // End the compilation event. + compilationEvent.end(); + + filter.remove(); + + if (printAfterCompilation || printCompilation) { + final long threadId = Thread.currentThread().getId(); + final long stop = TimeSource.getTimeNS(); + 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 = Lazy.threadMXBean.getThreadAllocatedBytes(threadId); + final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; + + if (printAfterCompilation) { + TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); + } else if (printCompilation) { + TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); + } + } + } + + if (result != null) { + try (DebugCloseable b = CodeInstallationTime.start()) { + installMethod(result); + } + } + stats.finish(method, installedCode); + if (result != null) { + return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); + } + return null; + } + } static class Lazy { /** @@ -102,12 +186,33 @@ public class CompilationTask { static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); } - public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) { + public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault, + OptionValues options) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.compilationId = new HotSpotCompilationIdentifier(request); this.useProfilingInfo = useProfilingInfo; this.installAsDefault = installAsDefault; + + /* + * Disable inlining if HotSpot has it disabled unless it's been explicitly set in Graal. + */ + HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); + GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); + OptionValues newOptions = options; + if (!config.inline) { + EconomicMap, Object> m = OptionValues.newOptionMap(); + if (Inline.getValue(options) && !Inline.hasBeenSet(options)) { + m.put(Inline, false); + } + if (InlineDuringParsing.getValue(options) && !InlineDuringParsing.hasBeenSet(options)) { + m.put(InlineDuringParsing, false); + } + if (!m.isEmpty()) { + newOptions = new OptionValues(options, m); + } + } + this.options = newOptions; } public HotSpotResolvedJavaMethod getMethod() { @@ -173,9 +278,8 @@ public class CompilationTask { public HotSpotCompilationRequestResult runCompilation() { HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); - final long threadId = Thread.currentThread().getId(); int entryBCI = getEntryBCI(); - final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotResolvedJavaMethod method = getMethod(); // register the compilation id in the method metrics @@ -190,85 +294,25 @@ public class CompilationTask { // Log a compilation event. EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); - // If there is already compiled code for this method on our level we simply return. - // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we - // only need to check for that value. - if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) { - return null; + if (installAsDefault) { + // If there is already compiled code for this method on our level we simply return. + // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we + // only need to check for that value. + if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) { + return HotSpotCompilationRequestResult.failure("Already compiled", false); + } } - CompilationResult result = null; + RetryableCompilation compilation = new RetryableCompilation(compilationEvent); try (DebugCloseable a = CompilationTime.start()) { - CompilationStatistics stats = CompilationStatistics.create(method, isOSR); - final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); - final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed(); - if (printCompilation) { - TTY.println(getMethodDescription() + "..."); - } - - TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); - final long start; - final long allocatedBytesBefore; - if (printAfterCompilation || printCompilation) { - start = TimeSource.getTimeNS(); - allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L; - } else { - start = 0L; - allocatedBytesBefore = 0L; - } - - try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { - // Begin the compilation event. - compilationEvent.begin(); - /* - * Disable inlining if HotSpot has it disabled unless it's been explicitly set in - * Graal. - */ - boolean disableInlining = !config.inline && !Inline.hasBeenSet(); - try (OverrideScope s1 = disableInlining ? OptionValue.override(Inline, false) : null) { - result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId); - } - } catch (Throwable e) { - throw Debug.handle(e); - } finally { - // End the compilation event. - compilationEvent.end(); - - filter.remove(); - - if (printAfterCompilation || printCompilation) { - final long stop = TimeSource.getTimeNS(); - 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 = Lazy.threadMXBean.getThreadAllocatedBytes(threadId); - final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; - - if (printAfterCompilation) { - TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); - } else if (printCompilation) { - TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); - } - } - } - - if (result != null) { - try (DebugCloseable b = CodeInstallationTime.start()) { - installMethod(result); - } - } - stats.finish(method, installedCode); - if (result != null) { - return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); - } - return null; + return compilation.execute(); } catch (BailoutException bailout) { BAILOUTS.increment(); - if (ExitVMOnBailout.getValue()) { + if (ExitVMOnBailout.getValue(options)) { TTY.out.println(method.format("Bailout in %H.%n(%p)")); bailout.printStackTrace(TTY.out); System.exit(-1); - } else if (PrintBailout.getValue()) { + } else if (PrintBailout.getValue(options)) { TTY.out.println(method.format("Bailout in %H.%n(%p)")); bailout.printStackTrace(TTY.out); } @@ -279,7 +323,7 @@ public class CompilationTask { * will happen if retry is false. */ final boolean permanentBailout = bailout.isPermanent(); - if (permanentBailout && PrintBailout.getValue()) { + if (permanentBailout && PrintBailout.getValue(options)) { TTY.println("Permanent bailout %s compiling method %s %s.", bailout.getMessage(), HotSpotGraalCompiler.str(method), (isOSR ? "OSR" : "")); } return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !permanentBailout); @@ -303,8 +347,9 @@ public class CompilationTask { try { int compiledBytecodes = 0; int codeSize = 0; - if (result != null) { - compiledBytecodes = result.getBytecodeSize(); + + if (compilation.result != null) { + compiledBytecodes = compilation.result.getBytecodeSize(); CompiledBytecodes.add(compiledBytecodes); if (installedCode != null) { codeSize = installedCode.getSize(); @@ -318,7 +363,7 @@ public class CompilationTask { compilationEvent.setMethod(method.format("%H.%n(%p)")); compilationEvent.setCompileId(getId()); compilationEvent.setCompileLevel(config.compilationLevelFullOptimization); - compilationEvent.setSucceeded(result != null && installedCode != null); + compilationEvent.setSucceeded(compilation.result != null && installedCode != null); compilationEvent.setIsOsr(isOSR); compilationEvent.setCodeSize(codeSize); compilationEvent.setInlinedBytes(compiledBytecodes); @@ -335,8 +380,8 @@ public class CompilationTask { * Automatically enable ExitVMOnException during bootstrap or when asserts are enabled but * respect ExitVMOnException if it's been explicitly set. */ - boolean exitVMOnException = ExitVMOnException.getValue(); - if (!ExitVMOnException.hasBeenSet()) { + boolean exitVMOnException = ExitVMOnException.getValue(options); + if (!ExitVMOnException.hasBeenSet(options)) { assert (exitVMOnException = true) == true; if (!exitVMOnException) { HotSpotGraalRuntimeProvider runtime = compiler.getGraalRuntime(); @@ -346,7 +391,7 @@ public class CompilationTask { } } - if (PrintStackTraceOnException.getValue() || exitVMOnException) { + if (PrintStackTraceOnException.getValue(options) || exitVMOnException) { try { t.printStackTrace(TTY.out); } catch (Throwable throwable) { @@ -368,14 +413,11 @@ public class CompilationTask { @SuppressWarnings("try") private void installMethod(final CompilationResult compResult) { final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache(); + HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend(); installedCode = null; Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; - try (Scope s = Debug.scope("CodeInstall", context)) { - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(getRequest().getMethod(), getRequest(), compResult); - installedCode = (HotSpotInstalledCode) codeCache.installCode(getRequest().getMethod(), compiledCode, null, getRequest().getMethod().getSpeculationLog(), installAsDefault); - } catch (Throwable e) { - throw Debug.handle(e); - } + installedCode = (HotSpotInstalledCode) backend.createInstalledCode(getRequest().getMethod(), getRequest(), compResult, + getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java index eb9532cdccb..14a95d28592 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java @@ -28,8 +28,9 @@ import java.util.Arrays; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -53,12 +54,12 @@ class CompilationWatchDog extends Thread implements AutoCloseable { public static class Options { // @formatter:off @Option(help = "Delay in seconds before watch dog monitoring a compilation (0 disables monitoring).", type = OptionType.Debug) - public static final OptionValue CompilationWatchDogStartDelay = new OptionValue<>(30.0D); + public static final OptionKey CompilationWatchDogStartDelay = new OptionKey<>(0.0D); @Option(help = "Interval in seconds between a watch dog reporting stack traces for long running compilations.", type = OptionType.Debug) - public static final OptionValue CompilationWatchDogStackTraceInterval = new OptionValue<>(30.0D); + public static final OptionKey CompilationWatchDogStackTraceInterval = new OptionKey<>(60.0D); @Option(help = "Number of contiguous identical compiler thread stack traces allowed before the VM exits " + "on the basis of a stuck compilation.", type = OptionType.Debug) - public static final OptionValue NonFatalIdenticalCompilationSnapshots = new OptionValue<>(10); + public static final OptionKey NonFatalIdenticalCompilationSnapshots = new OptionKey<>(20); // @formatter:on } @@ -90,12 +91,12 @@ class CompilationWatchDog extends Thread implements AutoCloseable { * this time period and thus not be actively monitored by the watch dog. */ private static final int SPIN_TIMEOUT_MS = 1000; - private static final long START_DELAY_MS = ms(Options.CompilationWatchDogStartDelay.getValue()); - private static final long STACK_TRACE_INTERVAL_MS = ms(Options.CompilationWatchDogStackTraceInterval.getValue()); - private static final boolean ENABLED = START_DELAY_MS > 0.0D; private WatchDogState state = WatchDogState.SLEEPING; private final Thread compilerThread; + private final long startDelayMilliseconds; + private final long stackTraceIntervalMilliseconds; + private final int nonFatalIdenticalCompilationSnapshots; private volatile ResolvedJavaMethod currentMethod; private volatile int currentId; private ResolvedJavaMethod lastWatched; @@ -106,11 +107,14 @@ class CompilationWatchDog extends Thread implements AutoCloseable { private int numberOfIdenticalStackTraces; private StackTraceElement[] lastStackTrace; - CompilationWatchDog(Thread compilerThread) { + CompilationWatchDog(Thread compilerThread, long startDelayMilliseconds, long stackTraceIntervalMilliseconds, int nonFatalIdenticalCompilationSnapshots) { this.compilerThread = compilerThread; this.setName("WatchDog" + getId() + "[" + compilerThread.getName() + "]"); this.setPriority(Thread.MAX_PRIORITY); this.setDaemon(true); + this.startDelayMilliseconds = startDelayMilliseconds; + this.stackTraceIntervalMilliseconds = stackTraceIntervalMilliseconds; + this.nonFatalIdenticalCompilationSnapshots = nonFatalIdenticalCompilationSnapshots; } public void startCompilation(ResolvedJavaMethod method, int id) { @@ -183,8 +187,8 @@ class CompilationWatchDog extends Thread implements AutoCloseable { @Override public void run() { - trace("Started%n", this); try { + trace("Started%n", this); while (true) { // get a copy of the last set method final ResolvedJavaMethod currentlyCompiling = currentMethod; @@ -200,25 +204,27 @@ class CompilationWatchDog extends Thread implements AutoCloseable { tick(WatchDogState.WATCHING_WITHOUT_STACK_INSPECTION); break; case WATCHING_WITHOUT_STACK_INSPECTION: - if (currentlyCompiling == lastWatched) { - if (elapsed >= START_DELAY_MS) { + if (currentlyCompiling.equals(lastWatched)) { + if (elapsed >= startDelayMilliseconds) { // we looked at the same compilation for a certain time // so now we start to collect stack traces tick(WatchDogState.WATCHING_WITH_STACK_INSPECTION); trace("changes mode to watching with stack traces"); } else { - // we still compile the same method but won't collect traces yet + // we still compile the same method but won't collect traces + // yet trace("watching without stack traces [%.2f seconds]", secs(elapsed)); } elapsed += SPIN_TIMEOUT_MS; } else { - // compilation finished before we exceeded initial watching period + // compilation finished before we exceeded initial watching + // period reset(); } break; case WATCHING_WITH_STACK_INSPECTION: - if (currentlyCompiling == lastWatched) { - if (elapsed >= START_DELAY_MS + (traceIntervals * STACK_TRACE_INTERVAL_MS)) { + if (currentlyCompiling.equals(lastWatched)) { + if (elapsed >= startDelayMilliseconds + (traceIntervals * stackTraceIntervalMilliseconds)) { trace("took a stack trace"); boolean newStackTrace = recordStackTrace(compilerThread.getStackTrace()); if (!newStackTrace) { @@ -226,7 +232,7 @@ class CompilationWatchDog extends Thread implements AutoCloseable { numberOfIdenticalStackTraces = 0; } numberOfIdenticalStackTraces++; - if (numberOfIdenticalStackTraces > Options.NonFatalIdenticalCompilationSnapshots.getValue()) { + if (numberOfIdenticalStackTraces > nonFatalIdenticalCompilationSnapshots) { synchronized (CompilationWatchDog.class) { TTY.printf("======================= WATCH DOG THREAD =======================%n" + "%s took %d identical stack traces, which indicates a stuck compilation (id=%d) of %s%n%sExiting VM%n", this, @@ -247,7 +253,8 @@ class CompilationWatchDog extends Thread implements AutoCloseable { } elapsed += SPIN_TIMEOUT_MS; } else { - // compilation finished before we are able to collect stack traces + // compilation finished before we are able to collect stack + // traces reset(); } break; @@ -255,16 +262,29 @@ class CompilationWatchDog extends Thread implements AutoCloseable { break; } } - Thread.sleep(SPIN_TIMEOUT_MS); + try { + Thread.sleep(SPIN_TIMEOUT_MS); + } catch (InterruptedException e) { + // Silently swallow + } } + } catch (VirtualMachineError vmError) { + /* + * We encounter a VM error. This includes for example OutOfMemoryExceptions. In such a + * case we silently swallow the error. If it happens again the application thread will + * most likely encounter the same problem. If not the watchdog thread will no longer + * monitor the compilation and thus the error cannot happen again. + */ } catch (Throwable t) { - synchronized (CompilationWatchDog.class) { - TTY.printf("%s encountered an exception%n%s%n", this, fmt(t)); - } + /* + * A real exception happened on the compilation watchdog. This is unintended behavior + * and must not happen in any case. + */ + throw new InternalError(String.format("%s encountered an exception%n%s%n", this, fmt(t)), t); } } - private static final ThreadLocal WATCH_DOGS = ENABLED ? new ThreadLocal<>() : null; + private static final ThreadLocal WATCH_DOGS = new ThreadLocal<>(); /** * Opens a scope for watching the compilation of a given method. @@ -276,13 +296,16 @@ class CompilationWatchDog extends Thread implements AutoCloseable { * is the whole compilation so that leaving the scope will cause {@link #close()} to be * called. */ - static CompilationWatchDog watch(ResolvedJavaMethod method, int id) { - if (ENABLED) { + static CompilationWatchDog watch(ResolvedJavaMethod method, int id, OptionValues options) { + long startDelayMilliseconds = ms(Options.CompilationWatchDogStartDelay.getValue(options)); + if (startDelayMilliseconds > 0.0D) { // Lazily get a watch dog thread for the current compiler thread CompilationWatchDog watchDog = WATCH_DOGS.get(); if (watchDog == null) { Thread currentThread = currentThread(); - watchDog = new CompilationWatchDog(currentThread); + long stackTraceIntervalMilliseconds = ms(Options.CompilationWatchDogStackTraceInterval.getValue(options)); + int nonFatalIdenticalCompilationSnapshots = Options.NonFatalIdenticalCompilationSnapshots.getValue(options); + watchDog = new CompilationWatchDog(currentThread, startDelayMilliseconds, stackTraceIntervalMilliseconds, nonFatalIdenticalCompilationSnapshots); WATCH_DOGS.set(watchDog); watchDog.start(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java deleted file mode 100644 index 4f3032dc49f..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot; - -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; - -/** - * Options related to {@link CompileTheWorld}. - * - * Note: This must be a top level class to work around for - * Eclipse bug 477597. - */ -public class CompileTheWorldOptions { - // @formatter:off - @Option(help = "Class path denoting methods to compile", type = OptionType.Debug) - public static final OptionValue CompileTheWorldClasspath = new OptionValue<>(CompileTheWorld.SUN_BOOT_CLASS_PATH); - @Option(help = "Verbose CompileTheWorld operation", type = OptionType.Debug) - public static final OptionValue CompileTheWorldVerbose = new OptionValue<>(true); - @Option(help = "The number of CompileTheWorld iterations to perform", type = OptionType.Debug) - public static final OptionValue CompileTheWorldIterations = new OptionValue<>(1); - @Option(help = "Only compile methods matching this filter", type = OptionType.Debug) - public static final OptionValue CompileTheWorldMethodFilter = new OptionValue<>(null); - @Option(help = "Exclude methods matching this filter from compilation", type = OptionType.Debug) - public static final OptionValue CompileTheWorldExcludeMethodFilter = new OptionValue<>(null); - @Option(help = "First class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) - public static final OptionValue CompileTheWorldStartAt = new OptionValue<>(1); - @Option(help = "Last class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) - public static final OptionValue CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE); - @Option(help = "Option value overrides to use during compile the world. For example, " + - "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " + - "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.", type = OptionType.Debug) - public static final OptionValue CompileTheWorldConfig = new OptionValue<>(null); - - @Option(help = "Run CTW using as many threads as there are processors on the system", type = OptionType.Debug) - public static final OptionValue CompileTheWorldMultiThreaded = new OptionValue<>(false); - @Option(help = "Number of threads to use for multithreaded CTW. Defaults to Runtime.getRuntime().availableProcessors()", type = OptionType.Debug) - public static final OptionValue CompileTheWorldThreads = new OptionValue<>(0); - // @formatter:on - - /** - * Overrides {@link #CompileTheWorldStartAt} and {@link #CompileTheWorldStopAt} from {@code -XX} - * HotSpot options of the same name if the latter have non-default values. - */ - public static void overrideWithNativeOptions(GraalHotSpotVMConfig c) { - if (c.compileTheWorldStartAt != 1) { - CompileTheWorldStartAt.setValue(c.compileTheWorldStartAt); - } - if (c.compileTheWorldStopAt != Integer.MAX_VALUE) { - CompileTheWorldStopAt.setValue(c.compileTheWorldStopAt); - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java index 3940a9a7057..b82a2054632 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java @@ -26,16 +26,18 @@ import static jdk.vm.ci.common.InitTimer.timer; import java.util.ArrayList; import java.util.Collections; -import java.util.IdentityHashMap; import java.util.List; import java.util.stream.Collectors; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.common.InitTimer; @@ -52,7 +54,7 @@ public abstract class CompilerConfigurationFactory implements Comparable CompilerConfiguration = new OptionValue<>(null); + public static final OptionKey CompilerConfiguration = new OptionKey<>(null); // @formatter:on } @@ -91,7 +93,7 @@ public abstract class CompilerConfigurationFactory implements Comparable, HotSpotBackendFactory> backends = new IdentityHashMap<>(); + private final EconomicMap, HotSpotBackendFactory> backends = EconomicMap.create(); @SuppressWarnings("try") public DefaultBackendMap(String backendName) { @@ -124,18 +126,11 @@ public abstract class CompilerConfigurationFactory implements Comparable factories = assertionsEnabled() ? new ArrayList<>() : null; + private static final List factories = Assertions.ENABLED ? new ArrayList<>() : null; private static boolean checkAndAddNewFactory(CompilerConfigurationFactory factory) { for (CompilerConfigurationFactory other : factories) { @@ -169,10 +164,10 @@ public abstract class CompilerConfigurationFactory implements Comparable*"); - public final int classMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "oop"); + public final boolean classMirrorIsHandle; + public final int classMirrorOffset; + { + String name = "Klass::_java_mirror"; + int offset = -1; + boolean isHandle = false; + try { + offset = getFieldOffset(name, Integer.class, "oop"); + } catch (JVMCIError e) { + + } + if (offset == -1) { + try { + offset = getFieldOffset(name, Integer.class, "jobject"); + isHandle = true; + } catch (JVMCIError e) { + + } + } + if (offset == -1) { + throw new JVMCIError("cannot get offset of field " + name + " with type oop or jobject"); + } + classMirrorOffset = offset; + classMirrorIsHandle = isHandle; + } public final int klassSuperKlassOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*"); public final int klassModifierFlagsOffset = getFieldOffset("Klass::_modifier_flags", Integer.class, "jint"); @@ -437,8 +463,15 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess { public final long markOopDescHashMaskInPlace = getConstant("markOopDesc::hash_mask_in_place", Long.class); public final int unlockedMask = getConstant("markOopDesc::unlocked_value", Integer.class); + public final int monitorMask = getConstant("markOopDesc::monitor_value", Integer.class, -1); public final int biasedLockPattern = getConstant("markOopDesc::biased_lock_pattern", Integer.class); + // This field has no type in vmStructs.cpp + public final int objectMonitorOwner = getFieldOffset("ObjectMonitor::_owner", Integer.class, null, -1); + public final int objectMonitorRecursions = getFieldOffset("ObjectMonitor::_recursions", Integer.class, "intptr_t", -1); + public final int objectMonitorCxq = getFieldOffset("ObjectMonitor::_cxq", Integer.class, "ObjectWaiter*", -1); + public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*", -1); + public final int markWordNoHashInPlace = getConstant("markOopDesc::no_hash_in_place", Integer.class); public final int markWordNoLockInPlace = getConstant("markOopDesc::no_lock_in_place", Integer.class); @@ -637,17 +670,17 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess { public final long sha256ImplCompressMB = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L); public final long sha512ImplCompress = getFieldValue("StubRoutines::_sha512_implCompress", Long.class, "address", 0L); public final long sha512ImplCompressMB = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L); - public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", 0L); + public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", longRequiredOnAMD64); public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L); public final long ghashProcessBlocks = getFieldValue("StubRoutines::_ghash_processBlocks", Long.class, "address", 0L); public final long crc32cTableTddr = getFieldValue("StubRoutines::_crc32c_table_addr", Long.class, "address", 0L); public final long updateBytesCRC32C = getFieldValue("StubRoutines::_updateBytesCRC32C", Long.class, "address", 0L); public final long updateBytesAdler32 = getFieldValue("StubRoutines::_updateBytesAdler32", Long.class, "address", 0L); - public final long squareToLen = getFieldValue("StubRoutines::_squareToLen", Long.class, "address", 0L); - public final long mulAdd = getFieldValue("StubRoutines::_mulAdd", Long.class, "address", 0L); - public final long montgomeryMultiply = getFieldValue("StubRoutines::_montgomeryMultiply", Long.class, "address", 0L); - public final long montgomerySquare = getFieldValue("StubRoutines::_montgomerySquare", Long.class, "address", 0L); + public final long squareToLen = getFieldValue("StubRoutines::_squareToLen", Long.class, "address", longRequiredOnAMD64); + public final long mulAdd = getFieldValue("StubRoutines::_mulAdd", Long.class, "address", longRequiredOnAMD64); + public final long montgomeryMultiply = getFieldValue("StubRoutines::_montgomeryMultiply", Long.class, "address", longRequiredOnAMD64); + 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); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index 1e72687e1b3..440a70dcdf5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -22,12 +22,7 @@ */ package org.graalvm.compiler.hotspot; -import static org.graalvm.compiler.hotspot.stubs.StubUtil.newDescriptor; - import java.util.EnumSet; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -38,8 +33,6 @@ import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; @@ -48,7 +41,6 @@ import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitution import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions; import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions; import org.graalvm.compiler.hotspot.replacements.SHASubstitutions; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; @@ -67,15 +59,19 @@ import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.nodes.UnwindNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.SuitesProvider; -import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.MapCursor; +import org.graalvm.word.Pointer; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompiledCode; -import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; import jdk.vm.ci.code.StackSlot; @@ -94,13 +90,11 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen public static class Options { // @formatter:off - @Option(help = "Use Graal stubs instead of HotSpot stubs where possible") - public static final OptionValue PreferGraalStubs = new OptionValue<>(false); @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible") - public static final OptionValue GraalArithmeticStubs = new OptionValue<>(true); + public static final OptionKey GraalArithmeticStubs = new OptionKey<>(true); @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." + " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug) - public static final OptionValue ASMInstructionProfiling = new OptionValue<>(null); + public static final OptionKey ASMInstructionProfiling = new OptionKey<>(null); // @formatter:on } @@ -134,16 +128,6 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen private final HotSpotGraalRuntimeProvider runtime; - /** - * @see DeoptimizationFetchUnrollInfoCallNode - */ - public static final ForeignCallDescriptor FETCH_UNROLL_INFO = new ForeignCallDescriptor("fetchUnrollInfo", Word.class, long.class, int.class); - - /** - * @see DeoptimizationStub#unpackFrames(ForeignCallDescriptor, Word, int) - */ - public static final ForeignCallDescriptor UNPACK_FRAMES = newDescriptor(DeoptimizationStub.class, "unpackFrames", int.class, Word.class, int.class); - /** * @see AESCryptSubstitutions#encryptBlockStub(ForeignCallDescriptor, Word, Word, Pointer) */ @@ -320,11 +304,6 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen public static final ForeignCallDescriptor INVOCATION_EVENT = new ForeignCallDescriptor("invocation_event", void.class, MethodCountersPointer.class); public static final ForeignCallDescriptor BACKEDGE_EVENT = new ForeignCallDescriptor("backedge_event", void.class, MethodCountersPointer.class, int.class, int.class); - /** - * @see UncommonTrapCallNode - */ - public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class, int.class); - public HotSpotBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { super(providers); this.runtime = runtime; @@ -339,8 +318,9 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * runtime} object was initialized and this backend was registered with it. * * @param jvmciRuntime + * @param options */ - public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime) { + public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { } /** @@ -349,8 +329,8 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * @param lir the LIR to examine * @return the registers that are defined by or used as temps for any instruction in {@code lir} */ - protected final Set gatherDestroyedCallerRegisters(LIR lir) { - final Set destroyedRegisters = new HashSet<>(); + protected final EconomicSet gatherDestroyedCallerRegisters(LIR lir) { + final EconomicSet destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY); ValueConsumer defConsumer = new ValueConsumer() { @Override @@ -382,7 +362,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen *

    * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove() * supports} pruning will have {@code destroyedRegisters} - * {@linkplain SaveRegistersOp#remove(Set) removed} as these registers are declared as + * {@linkplain SaveRegistersOp#remove(EconomicSet) removed} as these registers are declared as * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by * the stub's caller). * @@ -393,17 +373,17 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a virtual * slot to a frame slot index */ - protected void updateStub(Stub stub, Set destroyedRegisters, Map calleeSaveInfo, FrameMap frameMap) { + protected void updateStub(Stub stub, EconomicSet destroyedRegisters, EconomicMap calleeSaveInfo, FrameMap frameMap) { stub.initDestroyedCallerRegisters(destroyedRegisters); - for (Map.Entry e : calleeSaveInfo.entrySet()) { - SaveRegistersOp save = e.getValue(); + MapCursor cursor = calleeSaveInfo.getEntries(); + while (cursor.advance()) { + SaveRegistersOp save = cursor.getValue(); if (save.supportsRemove()) { save.remove(destroyedRegisters); } - DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo(); - if (info != null) { - info.setCalleeSaveInfo(save.getMap(frameMap)); + if (cursor.getKey() != LIRFrameState.NO_STATE) { + cursor.getKey().debugInfo().setCalleeSaveInfo(save.getMap(frameMap)); } } } @@ -419,7 +399,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen } protected void profileInstructions(LIR lir, CompilationResultBuilder crb) { - if (HotSpotBackend.Options.ASMInstructionProfiling.getValue() != null) { + if (HotSpotBackend.Options.ASMInstructionProfiling.getValue(lir.getOptions()) != null) { HotSpotInstructionProfiling.countInstructions(lir, crb.asm); } } @@ -427,7 +407,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen @Override public CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compResult) { HotSpotCompilationRequest compRequest = compilationRequest instanceof HotSpotCompilationRequest ? (HotSpotCompilationRequest) compilationRequest : null; - return HotSpotCompiledCodeBuilder.createCompiledCode(method, compRequest, compResult); + return HotSpotCompiledCodeBuilder.createCompiledCode(getCodeCache(), method, compRequest, compResult); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java similarity index 62% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java index 051b0443e40..8f8ea9e2ca5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java @@ -20,25 +20,21 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package org.graalvm.compiler.hotspot; -package org.graalvm.compiler.core.aarch64; +import jdk.vm.ci.code.CompiledCode; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; +public interface HotSpotCodeCacheListener { + /** + * Notifies this object on successful install into the CodeCache. + * + * @param codeCache the code cache into which the code was installed + * @param installedCode the code that was installed + * @param compiledCode the compiled code from which {@code installedCode} was produced + */ + default void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { -public class AArch64AddressLowering extends AddressLowering { - - @Override - public AddressNode lower(ValueNode address) { - return lower(address, null); } - - @Override - public AddressNode lower(ValueNode base, ValueNode offset) { - AArch64AddressNode ret = new AArch64AddressNode(base, offset); - // TODO improve - return base.graph().unique(ret); - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java index 79c83799076..ecae5c3b699 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java @@ -42,6 +42,7 @@ import org.graalvm.compiler.code.DataSection; import org.graalvm.compiler.code.SourceMapping; import org.graalvm.compiler.graph.NodeSourcePosition; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.ConstantReference; @@ -61,13 +62,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotCompiledCodeBuilder { - public static HotSpotCompiledCode createCompiledCode(ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) { + public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) { String name = compResult.getName(); byte[] targetCode = compResult.getTargetCode(); int targetCodeSize = compResult.getTargetCodeSize(); - Site[] sites = getSortedSites(compResult); + Site[] sites = getSortedSites(codeCache, compResult); Assumption[] assumptions = compResult.getAssumptions(); @@ -201,7 +202,7 @@ public class HotSpotCompiledCodeBuilder { * {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects * {@link Infopoint} PCs to be unique. */ - private static Site[] getSortedSites(CompilationResult target) { + private static Site[] getSortedSites(CodeCacheProvider codeCache, CompilationResult target) { List sites = new ArrayList<>( target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size()); sites.addAll(target.getExceptionHandlers()); @@ -214,9 +215,11 @@ public class HotSpotCompiledCodeBuilder { * can really be represented and recording the end PC seems to give the best results and * corresponds with what C1 and C2 do. */ - for (SourceMapping source : target.getSourceMappings()) { - sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION)); - assert verifySourcePositionReceivers(source.getSourcePosition()); + if (codeCache.shouldDebugNonSafepoints()) { + for (SourceMapping source : target.getSourceMappings()) { + sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION)); + assert verifySourcePositionReceivers(source.getSourcePosition()); + } } SiteComparator c = new SiteComparator(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java index 794f7674037..82f3ca48652 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java @@ -27,15 +27,14 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.Arrays; -import java.util.HashMap; - import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; @@ -102,7 +101,7 @@ public abstract class HotSpotCounterOp extends LIRInstruction { proc.apply(0, increments[0], displacement); } else { // Slow path with sort by displacements ascending int[] displacements = new int[names.length]; - HashMap offsetMap = new HashMap<>(names.length); + EconomicMap offsetMap = EconomicMap.create(); for (int i = 0; i < names.length; i++) { int arrayIndex = getIndex(names[i], groups[i], increments[i]); displacements[i] = getDisplacementForLongIndex(target, arrayIndex); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java index babe75eb3aa..614b7d72d17 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java @@ -24,8 +24,14 @@ package org.graalvm.compiler.hotspot; import static jdk.vm.ci.code.BytecodeFrame.isPlaceholderBci; +import java.util.ArrayList; +import java.util.List; + +import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.gen.DebugInfoBuilder; -import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.GraalGraphError; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.ValueNode; @@ -36,6 +42,8 @@ import jdk.vm.ci.code.StackLockValue; import jdk.vm.ci.code.VirtualObject; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.MetaUtil; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Extends {@link DebugInfoBuilder} to allocate the extra debug information required for locks. @@ -71,19 +79,48 @@ public class HotSpotDebugInfoBuilder extends DebugInfoBuilder { VirtualStackSlot slot = lockStack.makeLockSlot(lockDepth); ValueNode lock = state.lockAt(lockIndex); JavaValue object = toJavaValue(lock); - boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex) == null; - assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth; + boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex).isEliminated(); + assert state.monitorIdAt(lockIndex).getLockDepth() == lockDepth; return new StackLockValue(object, slot, eliminated); } @Override protected BytecodeFrame computeFrameForState(FrameState state) { if (isPlaceholderBci(state.bci) && state.bci != BytecodeFrame.BEFORE_BCI) { - // This is really a hard error since an incorrect state could crash hotspot - throw GraalError.shouldNotReachHere("Invalid state " + BytecodeFrame.getPlaceholderBciName(state.bci) + " " + state); + raiseInvalidFrameStateError(state); } BytecodeFrame result = super.computeFrameForState(state); maxInterpreterFrameSize = Math.max(maxInterpreterFrameSize, codeCacheProvider.interpreterFrameSize(result)); return result; } + + protected void raiseInvalidFrameStateError(FrameState state) throws GraalGraphError { + // This is a hard error since an incorrect state could crash hotspot + NodeSourcePosition sourcePosition = state.getNodeSourcePosition(); + List context = new ArrayList<>(); + ResolvedJavaMethod replacementMethodWithProblematicSideEffect = null; + if (sourcePosition != null) { + NodeSourcePosition pos = sourcePosition; + while (pos != null) { + StringBuilder sb = new StringBuilder("parsing "); + ResolvedJavaMethod method = pos.getMethod(); + MetaUtil.appendLocation(sb, method, pos.getBCI()); + if (method.getAnnotation(MethodSubstitution.class) != null || + method.getAnnotation(Snippet.class) != null) { + replacementMethodWithProblematicSideEffect = method; + } + context.add(sb.toString()); + pos = pos.getCaller(); + } + } + String message = "Invalid frame state " + state; + if (replacementMethodWithProblematicSideEffect != null) { + message += " associated with a side effect in " + replacementMethodWithProblematicSideEffect.format("%H.%n(%p)") + " at a position that cannot be deoptimized to"; + } + GraalGraphError error = new GraalGraphError(message); + for (String c : context) { + error.addContext(c); + } + throw error; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java index 82d665be703..d316d0050bf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -24,10 +24,10 @@ package org.graalvm.compiler.hotspot; import jdk.vm.ci.meta.InvokeTarget; -import org.graalvm.compiler.core.common.LocationIdentity; 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; /** * The details required to link a HotSpot runtime or stub call. @@ -96,6 +96,11 @@ public interface HotSpotForeignCallLinkage extends ForeignCallLinkage, InvokeTar */ boolean isCompiledStub(); + /** + * Gets the stub, if any, this foreign call links to. + */ + Stub getStub(); + void finalizeAddress(Backend backend); long getAddress(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java index c4e0d8d6bad..ca00da23648 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java @@ -25,14 +25,13 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import java.util.Set; - -import org.graalvm.compiler.core.common.LocationIdentity; 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.util.EconomicSet; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CallingConvention.Type; @@ -228,13 +227,24 @@ public class HotSpotForeignCallLinkageImpl extends HotSpotForeignCallTarget impl return address == 0L || stub != null; } + @Override + public Stub getStub() { + assert checkStubCondition(); + return stub; + } + + private boolean checkStubCondition() { + assert stub != null : "linkage without an address must be a stub - forgot to register a Stub associated with " + descriptor + "?"; + return true; + } + @Override public void finalizeAddress(Backend backend) { if (address == 0) { - assert stub != null : "linkage without an address must be a stub - forgot to register a Stub associated with " + descriptor + "?"; + assert checkStubCondition(); InstalledCode code = stub.getCode(backend); - Set destroyedRegisters = stub.getDestroyedCallerRegisters(); + EconomicSet destroyedRegisters = stub.getDestroyedCallerRegisters(); if (!destroyedRegisters.isEmpty()) { AllocatableValue[] temporaryLocations = new AllocatableValue[destroyedRegisters.size()]; int i = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java index f4951022ed6..348a82e9fea 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import java.io.ByteArrayOutputStream; @@ -32,6 +31,7 @@ import java.util.Formattable; import java.util.Formatter; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -40,9 +40,7 @@ import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.DebugEnvironment; import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TopLevelDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; import org.graalvm.compiler.hotspot.CompilationCounters.Options; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -56,6 +54,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; import org.graalvm.compiler.phases.PhaseSuite; @@ -64,7 +63,6 @@ import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -83,12 +81,12 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { private final CompilationCounters compilationCounters; private final BootstrapWatchDog bootstrapWatchDog; - HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime) { + HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, OptionValues options) { this.jvmciRuntime = jvmciRuntime; this.graalRuntime = graalRuntime; // It is sufficient to have one compilation counter object per Graal compiler object. - this.compilationCounters = Options.CompilationCountLimit.getValue() > 0 ? new CompilationCounters() : null; - this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue() ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; + this.compilationCounters = Options.CompilationCountLimit.getValue(options) > 0 ? new CompilationCounters(options) : null; + this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; } @Override @@ -97,31 +95,40 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { } @Override - @SuppressWarnings("try") public CompilationRequestResult compileMethod(CompilationRequest request) { - if (graalRuntime.isBootstrapping() && GraalDebugConfig.Options.BootstrapInitializeOnly.getValue()) { - return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", GraalDebugConfig.Options.BootstrapInitializeOnly.getName()), true); + return compileMethod(request, true); + } + + @SuppressWarnings("try") + CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault) { + if (graalRuntime.isShutdown()) { + return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false); } - if (bootstrapWatchDog != null && graalRuntime.isBootstrapping()) { - if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { - // Drain the compilation queue to expedite completion of the bootstrap - return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); + OptionValues options = graalRuntime.getOptions(request.getMethod()); + + if (graalRuntime.isBootstrapping()) { + if (GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options)) { + return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", GraalDebugConfig.Options.BootstrapInitializeOnly.getName()), true); + } + if (bootstrapWatchDog != null) { + if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { + // Drain the compilation queue to expedite completion of the bootstrap + return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); + } } } ResolvedJavaMethod method = request.getMethod(); HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request; - try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId()); + try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options); BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); - CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod();) { + CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) { if (compilationCounters != null) { compilationCounters.countCompilation(method); } // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(TTY.out, graalRuntime.getHostProviders().getSnippetReflection()); - } - CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, true); - CompilationRequestResult r = null; + DebugEnvironment.ensureInitialized(options, graalRuntime.getHostProviders().getSnippetReflection()); + CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, installAsDefault, options); + CompilationRequestResult r; try (DebugConfigScope dcs = Debug.setConfig(new TopLevelDebugConfig()); Debug.Scope s = Debug.methodMetricsScope("HotSpotGraalCompiler", MethodMetricsRootScopeInfo.create(method), true, method)) { r = task.runCompilation(); @@ -131,39 +138,31 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { } } - public void compileTheWorld() throws Throwable { - HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmciRuntime.getHostJVMCIBackend().getCodeCache(); - int iterations = CompileTheWorldOptions.CompileTheWorldIterations.getValue(); - for (int i = 0; i < iterations; i++) { - codeCache.resetCompilationStatistics(); - TTY.println("CompileTheWorld : iteration " + i); - CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, this); - ctw.compile(); - } - System.exit(0); - } - - public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId) { + public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options) { HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; - StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId); + StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId, options); if (graph == null) { SpeculationLog speculationLog = method.getSpeculationLog(); if (speculationLog != null) { speculationLog.collectFailedSpeculations(); } - graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()), speculationLog, useProfilingInfo, compilationId); + graph = new StructuredGraph.Builder(options, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog( + speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build(); } - Suites suites = getSuites(providers); - LIRSuites lirSuites = getLIRSuites(providers); + Suites suites = getSuites(providers, options); + LIRSuites lirSuites = getLIRSuites(providers, options); ProfilingInfo profilingInfo = useProfilingInfo ? method.getProfilingInfo(!isOSR, isOSR) : DefaultProfilingInfo.get(TriState.FALSE); - OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); - if (isOSR) { - // In OSR compiles, we cannot rely on never executed code profiles, because - // all code after the OSR loop is never executed. + OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo, options); + + /* + * Cut off never executed code profiles if there is code, e.g. after the osr loop, that is + * never executed. + */ + if (isOSR && !OnStackReplacementPhase.Options.DeoptAfterOSR.getValue(options)) { optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); } CompilationResult result = new CompilationResult(); @@ -186,19 +185,21 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { * * @param method * @param compilationId + * @param options * @return an intrinsic graph that can be compiled and installed for {@code method} or null */ @SuppressWarnings("try") - public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId) { + public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId, OptionValues options) { Replacements replacements = providers.getReplacements(); - ResolvedJavaMethod substMethod = replacements.getSubstitutionMethod(method); - if (substMethod != null) { + Bytecode subst = replacements.getSubstitutionBytecode(method); + if (subst != null) { + ResolvedJavaMethod substMethod = subst.getMethod(); assert !substMethod.equals(method); - StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES, NO_PROFILING_INFO, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(options, AllowAssumptions.YES).method(substMethod).compilationId(compilationId).build(); try (Debug.Scope scope = Debug.scope("GetIntrinsicGraph", graph)) { Plugins plugins = new Plugins(providers.getGraphBuilderPlugins()); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); - IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, replacements.getReplacementBytecodeProvider(), ROOT_COMPILATION); + IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, subst.getOrigin(), ROOT_COMPILATION); new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); assert !graph.isFrozen(); @@ -210,16 +211,16 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { return null; } - protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) { - return new OptimisticOptimizations(profilingInfo); + protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo, OptionValues options) { + return new OptimisticOptimizations(profilingInfo, options); } - protected Suites getSuites(HotSpotProviders providers) { - return providers.getSuites().getDefaultSuites(); + protected Suites getSuites(HotSpotProviders providers, OptionValues options) { + return providers.getSuites().getDefaultSuites(options); } - protected LIRSuites getLIRSuites(HotSpotProviders providers) { - return providers.getSuites().getDefaultLIRSuites(); + protected LIRSuites getLIRSuites(HotSpotProviders providers, OptionValues options) { + return providers.getSuites().getDefaultLIRSuites(options); } /** @@ -245,6 +246,11 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); } if (isOSR) { + // We must not clear non liveness for OSR compilations. + GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); + GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); + GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); + newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); newGbs.appendPhase(new OnStackReplacementPhase()); } return newGbs; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java index cab5141f0ad..f3f3186f157 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java @@ -23,23 +23,15 @@ package org.graalvm.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; -import static org.graalvm.compiler.options.OptionValue.PROFILE_OPTIONVALUE_PROPERTY_NAME; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; import java.io.PrintStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.ServiceLoader; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; @@ -48,35 +40,11 @@ import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotSignature; import jdk.vm.ci.runtime.JVMCIRuntime; -import jdk.vm.ci.services.Services; public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory { - /** - * The name of the system property specifying a file containing extra Graal option settings. - */ - private static final String GRAAL_OPTIONS_FILE_PROPERTY_NAME = "graal.options.file"; - - /** - * The name of the system property specifying the Graal version. - */ - private static final String GRAAL_VERSION_PROPERTY_NAME = "graal.version"; - - /** - * The prefix for system properties that correspond to {@link Option} annotated fields. A field - * named {@code MyOption} will have its value set from a system property with the name - * {@code GRAAL_OPTION_PROPERTY_PREFIX + "MyOption"}. - */ - public static final String GRAAL_OPTION_PROPERTY_PREFIX = "graal."; - private static MethodFilter[] graalCompileOnlyFilter; - - /** - * Gets the system property assignment that would set the current value for a given option. - */ - public static String asSystemPropertySetting(OptionValue value) { - return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(); - } + private static boolean compileGraalWithC1Only; private final HotSpotGraalJVMCIServiceLocator locator; @@ -89,125 +57,58 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return "graal"; } + /** + * Initialized when this factory is {@linkplain #onSelection() selected}. + */ + private OptionValues options; + @Override public void onSelection() { - initializeOptions(); JVMCIVersionCheck.check(false); + assert options == null : "cannot select " + getClass() + " service more than once"; + options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + initializeGraalCompilePolicyFields(options); + /* + * 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. + */ + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); + } + + private static void initializeGraalCompilePolicyFields(OptionValues options) { + compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options); + String optionValue = Options.GraalCompileOnly.getValue(options); + if (optionValue != null) { + MethodFilter[] filter = MethodFilter.parse(optionValue); + if (filter.length == 0) { + filter = null; + } + graalCompileOnlyFilter = filter; + } } @Override public void printProperties(PrintStream out) { - ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); out.println("[Graal properties]"); - OptionsParser.printFlags(loader, out, allOptionsSettings.keySet(), GRAAL_OPTION_PROPERTY_PREFIX); + options.printHelp(OptionsParser.getOptionsLoader(), out, GRAAL_OPTION_PROPERTY_PREFIX); } static class Options { // @formatter:off @Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert) - public static final OptionValue CompileGraalWithC1Only = new OptionValue<>(true); - - @Option(help = "Hook into VM-level mechanism for denoting compilations to be performed in first tier.", type = OptionType.Expert) - public static final OptionValue UseTrivialPrefixes = new OptionValue<>(false); + public static final OptionKey CompileGraalWithC1Only = new OptionKey<>(true); @Option(help = "A method filter selecting what should be compiled by Graal. All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert) - public static final OptionValue GraalCompileOnly = new OptionValue<>(null); + public static final OptionKey GraalCompileOnly = new OptionKey<>(null); // @formatter:on } - private static Map allOptionsSettings; - - /** - * Initializes options if they haven't already been initialized. - * - * Initialization means first parsing the options in the file denoted by the - * {@code VM.getSavedProperty(String) saved} system property named - * {@value HotSpotGraalCompilerFactory#GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists - * followed by parsing the options encoded in saved system properties whose names start with - * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned - * file with {@link Properties#load(java.io.Reader)}. - */ - @SuppressWarnings("try") - private static synchronized void initializeOptions() { - if (allOptionsSettings == null) { - try (InitTimer t = timer("InitializeOptions")) { - ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); - Map savedProps = Services.getSavedProperties(); - String optionsFile = savedProps.get(GRAAL_OPTIONS_FILE_PROPERTY_NAME); - - if (optionsFile != null) { - File graalOptions = new File(optionsFile); - if (graalOptions.exists()) { - try (FileReader fr = new FileReader(graalOptions)) { - Properties props = new Properties(); - props.load(fr); - Map optionSettings = new HashMap<>(); - for (Map.Entry e : props.entrySet()) { - optionSettings.put((String) e.getKey(), (String) e.getValue()); - } - try { - OptionsParser.parseOptions(optionSettings, null, loader); - if (allOptionsSettings == null) { - allOptionsSettings = new HashMap<>(optionSettings); - } else { - allOptionsSettings.putAll(optionSettings); - } - } catch (Throwable e) { - throw new InternalError("Error parsing an option from " + graalOptions, e); - } - } catch (IOException e) { - throw new InternalError("Error reading " + graalOptions, e); - } - } - } - - Map optionSettings = new HashMap<>(); - for (Entry e : savedProps.entrySet()) { - String name = e.getKey(); - if (name.startsWith(GRAAL_OPTION_PROPERTY_PREFIX)) { - if (name.equals("graal.PrintFlags") || name.equals("graal.ShowFlags")) { - System.err.println("The " + name + " option has been removed and will be ignored. Use -XX:+JVMCIPrintProperties instead."); - } else if (name.equals(GRAAL_OPTIONS_FILE_PROPERTY_NAME) || name.equals(GRAAL_VERSION_PROPERTY_NAME) || name.equals(PROFILE_OPTIONVALUE_PROPERTY_NAME)) { - // Ignore well known properties that do not denote an option - } else { - String value = e.getValue(); - optionSettings.put(name.substring(GRAAL_OPTION_PROPERTY_PREFIX.length()), value); - } - } - } - - OptionsParser.parseOptions(optionSettings, null, loader); - - if (allOptionsSettings == null) { - allOptionsSettings = optionSettings; - } else { - allOptionsSettings.putAll(optionSettings); - } - - if (Options.GraalCompileOnly.getValue() != null) { - graalCompileOnlyFilter = MethodFilter.parse(Options.GraalCompileOnly.getValue()); - if (graalCompileOnlyFilter.length == 0) { - graalCompileOnlyFilter = null; - } - } - if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue()) { - /* - * 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. - */ - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); - } - } - } - } - @Override public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { - HotSpotGraalCompiler compiler = createCompiler(runtime, CompilerConfigurationFactory.selectFactory(null)); + HotSpotGraalCompiler compiler = createCompiler(runtime, options, CompilerConfigurationFactory.selectFactory(null, options)); // Only the HotSpotGraalRuntime associated with the compiler created via // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving // VM events. @@ -223,36 +124,24 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration} */ @SuppressWarnings("try") - public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, CompilerConfigurationFactory compilerConfigurationFactory) { + public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) { HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime; try (InitTimer t = timer("HotSpotGraalRuntime.")) { - HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory); - return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime); + HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options); + return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime, graalRuntime.getOptions()); } } - @Override - public String[] getTrivialPrefixes() { - if (Options.UseTrivialPrefixes.getValue()) { - if (Options.CompileGraalWithC1Only.getValue()) { - return new String[]{"jdk/vm/ci", "org/graalvm/compiler", "com/oracle/graal"}; - } - } - return null; - } - @Override public CompilationLevelAdjustment getCompilationLevelAdjustment() { if (graalCompileOnlyFilter != null) { return CompilationLevelAdjustment.ByFullSignature; } - if (!Options.UseTrivialPrefixes.getValue()) { - if (Options.CompileGraalWithC1Only.getValue()) { - // We only decide using the class declaring the method - // so no need to have the method name and signature - // symbols converted to a String. - return CompilationLevelAdjustment.ByHolder; - } + if (compileGraalWithC1Only) { + // We only decide using the class declaring the method + // so no need to have the method name and signature + // symbols converted to a String. + return CompilationLevelAdjustment.ByHolder; } return CompilationLevelAdjustment.None; } @@ -262,6 +151,13 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return adjustCompilationLevelInternal(declaringClass, name, signature, level); } + static { + // Fail-fast detection for package renaming to guard use of package + // prefixes in adjustCompilationLevelInternal. + assert jdk.vm.ci.services.Services.class.getName().equals("jdk.vm.ci.services.Services"); + assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory"); + } + /* * This method is static so it can be exercised during initialization. */ @@ -281,10 +177,12 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return CompilationLevel.Simple; } } - if (level.ordinal() > CompilationLevel.Simple.ordinal()) { - String declaringClassName = declaringClass.getName(); - if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm.compiler") || declaringClassName.startsWith("com.oracle.graal")) { - return CompilationLevel.Simple; + if (compileGraalWithC1Only) { + if (level.ordinal() > CompilationLevel.Simple.ordinal()) { + String declaringClassName = declaringClass.getName(); + if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) { + return CompilationLevel.Simple; + } } } return level; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java new file mode 100644 index 00000000000..826eb0f2d02 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java @@ -0,0 +1,380 @@ +/* + * 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.management.ManagementFactory; +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 javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.DynamicMBean; +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; +import javax.management.ReflectionException; +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.GraalDebugConfig; +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.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; +import org.graalvm.util.UnmodifiableEconomicMap; + +public final class HotSpotGraalMBean implements DynamicMBean { + private static Object mBeanServerField; + private final HotSpotGraalCompiler compiler; + private final OptionValues options; + private final EconomicMap, Object> changes; + private final EconomicSet methodDumps; + private volatile EconomicSet> loaders; + private 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> 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 = ManagementFactory.class.getDeclaredField("platformMBeanServer"); + field.setAccessible(true); + mBeanServerField = field; + } catch (Exception ex) { + mBeanServerField = 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 ObjectName ensureRegistered(boolean check) { + for (int cnt = 0;; cnt++) { + if (registered != null) { + return registered; + } + if (check && !isMXServerOn()) { + return null; + } + try { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName name = new ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt)); + mbs.registerMBean(this, name); + registered = name; + break; + } catch (MalformedObjectNameException | MBeanRegistrationException | NotCompliantMBeanException ex) { + throw new IllegalStateException(ex); + } catch (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 addNewRef = new WeakReference<>(clazz.getClassLoader()); + if (!loaders.contains(addNewRef)) { + EconomicSet> 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, GraalDebugConfig.Options.Dump, request.filter, + GraalDebugConfig.Options.PrintGraphHost, request.host, + GraalDebugConfig.Options.PrintBinaryGraphPort, request.port); + break; + } + } + } + return current; + } + + @Override + public Object getAttribute(String attribute) { + UnmodifiableEconomicMap, 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(Attribute attribute) throws AttributeNotFoundException { + Attribute newAttr = setImpl(attribute); + if (newAttr == null) { + throw new AttributeNotFoundException(); + } + } + + private Attribute setImpl(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 AttributeList getAttributes(String[] names) { + AttributeList list = new AttributeList(); + for (String name : names) { + Object value = getAttribute(name); + if (value != null) { + list.add(new Attribute(name, value)); + } + } + return list; + } + + @Override + public AttributeList setAttributes(AttributeList attributes) { + AttributeList setOk = new AttributeList(); + for (Attribute attr : attributes.asList()) { + Attribute newAttr = setImpl(attr); + if (newAttr != null) { + setOk.add(newAttr); + } + } + return setOk; + } + + @Override + public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, 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 ReflectionException(ex); + } + } + return null; + } + + private static T param(Object[] arr, int index, String name, Class 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 MBeanException { + String jvmName = MetaUtil.toInternalName(className); + methodDumps.add(new Dump(host, port, jvmName, methodName, filter)); + + ClassNotFoundException last = null; + EconomicSet> found = EconomicSet.create(); + Iterator> it = loaders.iterator(); + while (it.hasNext()) { + Reference 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 MBeanException(last, "Cannot find class " + className + " to schedule recompilation"); + } + } + + @Override + public MBeanInfo getMBeanInfo() { + List attrs = new ArrayList<>(); + if (registered != null) { + for (OptionDescriptor descr : allOptionDescriptors()) { + attrs.add(new MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false)); + } + } + 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( + HotSpotGraalMBean.class.getName(), + "Graal", + attrs.toArray(new MBeanAttributeInfo[attrs.size()]), + null, ops, null); + } + + private static Iterable allOptionDescriptors() { + List 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(); + } + + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java new file mode 100644 index 00000000000..2fde550dd64 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java @@ -0,0 +1,139 @@ +/* + * 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 static jdk.vm.ci.common.InitTimer.timer; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + +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 org.graalvm.util.EconomicMap; + +import jdk.vm.ci.common.InitTimer; + +/** + * 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 { + + /** + * The name of the system property specifying a file containing extra Graal option settings. + */ + private static final String GRAAL_OPTIONS_FILE_PROPERTY_NAME = "graal.options.file"; + + /** + * The name of the system property specifying the Graal version. + */ + private static final String GRAAL_VERSION_PROPERTY_NAME = "graal.version"; + + /** + * The prefix for system properties that correspond to {@link Option} annotated fields. A field + * named {@code MyOption} will have its value set from a system property with the name + * {@code GRAAL_OPTION_PROPERTY_PREFIX + "MyOption"}. + */ + public static final String GRAAL_OPTION_PROPERTY_PREFIX = "graal."; + + /** + * Gets the system property assignment that would set the current value for a given option. + */ + public static String asSystemPropertySetting(OptionValues options, OptionKey value) { + return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(options); + } + + public static final OptionValues HOTSPOT_OPTIONS = initializeOptions(); + + /** + * Global options. The values for these options are initialized by parsing the file denoted by + * the {@code VM.getSavedProperty(String) saved} system property named + * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists followed by parsing the options + * encoded in saved system properties whose names start with + * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned + * file with {@link Properties#load(java.io.Reader)}. + */ + @SuppressWarnings("try") + private static OptionValues initializeOptions() { + EconomicMap, Object> values = OptionValues.newOptionMap(); + try (InitTimer t = timer("InitializeOptions")) { + + Iterable loader = OptionsParser.getOptionsLoader(); + Map savedProps = jdk.vm.ci.services.Services.getSavedProperties(); + String optionsFile = savedProps.get(GRAAL_OPTIONS_FILE_PROPERTY_NAME); + + if (optionsFile != null) { + File graalOptions = new File(optionsFile); + if (graalOptions.exists()) { + try (FileReader fr = new FileReader(graalOptions)) { + Properties props = new Properties(); + props.load(fr); + EconomicMap optionSettings = EconomicMap.create(); + for (Map.Entry e : props.entrySet()) { + optionSettings.put((String) e.getKey(), (String) e.getValue()); + } + try { + OptionsParser.parseOptions(optionSettings, values, loader); + } catch (Throwable e) { + throw new InternalError("Error parsing an option from " + graalOptions, e); + } + } catch (IOException e) { + throw new InternalError("Error reading " + graalOptions, e); + } + } + } + + EconomicMap optionSettings = EconomicMap.create(); + for (Map.Entry e : savedProps.entrySet()) { + String name = e.getKey(); + if (name.startsWith(GRAAL_OPTION_PROPERTY_PREFIX)) { + if (name.equals("graal.PrintFlags") || name.equals("graal.ShowFlags")) { + System.err.println("The " + name + " option has been removed and will be ignored. Use -XX:+JVMCIPrintProperties instead."); + } else if (name.equals(GRAAL_OPTIONS_FILE_PROPERTY_NAME) || name.equals(GRAAL_VERSION_PROPERTY_NAME)) { + // Ignore well known properties that do not denote an option + } else { + String value = e.getValue(); + optionSettings.put(name.substring(GRAAL_OPTION_PROPERTY_PREFIX.length()), value); + } + } + } + + OptionsParser.parseOptions(optionSettings, values, loader); + return new OptionValues(values); + } + } + + @Override + public OptionValues getOptions() { + return HOTSPOT_OPTIONS; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java index 401169124f4..e374768782a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java @@ -22,22 +22,36 @@ */ package org.graalvm.compiler.hotspot; +import static jdk.vm.ci.common.InitTimer.timer; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; -import static jdk.vm.ci.common.InitTimer.timer; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; -import org.graalvm.compiler.api.collections.CollectionsProvider; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalRuntime; import org.graalvm.compiler.core.common.GraalOptions; @@ -48,15 +62,18 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.internal.DebugValuesPrinter; import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.graph.DefaultNodeCollectionsProvider; -import org.graalvm.compiler.graph.NodeCollectionsProvider; +import org.graalvm.compiler.hotspot.CompilationStatistics.Options; import org.graalvm.compiler.hotspot.CompilerConfigurationFactory.BackendMap; 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.OptionValues; 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.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.stack.StackIntrospection; @@ -64,6 +81,7 @@ import jdk.vm.ci.common.InitTimer; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.runtime.JVMCIBackend; //JaCoCo Exclude @@ -87,28 +105,37 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { private final HotSpotBackend hostBackend; private DebugValuesPrinter debugValuesPrinter; + private final List snippetCounterGroups; - private final Map, HotSpotBackend> backends = new HashMap<>(); + private final EconomicMap, HotSpotBackend> backends = EconomicMap.create(Equivalence.IDENTITY); private final GraalHotSpotVMConfig config; + private final OptionValues options; + private final HotSpotGraalMBean mBean; + /** * @param compilerConfigurationFactory factory for the compiler configuration - * {@link CompilerConfigurationFactory#selectFactory(String)} + * {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)} */ @SuppressWarnings("try") - HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) { - + HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) { HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); - config = GeneratePIC.getValue() ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store); - CompileTheWorldOptions.overrideWithNativeOptions(config); + 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() == false) { - GraalOptions.HotSpotPrintInlining.setValue(config.printInlining); + if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) { + options = new OptionValues(initialOptions, HotSpotPrintInlining, true); + } else { + options = initialOptions; } + snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration(); + + HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions); + this.mBean = HotSpotGraalMBean.create(compiler); + BackendMap backendMap = compilerConfigurationFactory.createBackendMap(); JVMCIBackend hostJvmciBackend = jvmciRuntime.getHostJVMCIBackend(); @@ -136,16 +163,16 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { } } - if (Log.getValue() == null && !areScopedGlobalMetricsEnabled() && Dump.getValue() == null && Verify.getValue() == null) { - if (MethodFilter.getValue() != null && !Debug.isEnabled()) { + if (Log.getValue(options) == null && !areScopedGlobalMetricsEnabled(options) && Dump.getValue(options) == null && Verify.getValue(options) == null) { + if (MethodFilter.getValue(options) != null && !Debug.isEnabled()) { TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, TrackMemUse, Dump and Verify options are all null"); } } if (Debug.isEnabled()) { - DebugEnvironment.initialize(TTY.out, hostBackend.getProviders().getSnippetReflection()); + DebugEnvironment.ensureInitialized(options, hostBackend.getProviders().getSnippetReflection()); - String summary = DebugValueSummary.getValue(); + String summary = DebugValueSummary.getValue(options); if (summary != null) { switch (summary) { case "Name": @@ -160,12 +187,12 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { } if (Debug.areUnconditionalCountersEnabled() || Debug.areUnconditionalTimersEnabled() || Debug.areUnconditionalMethodMetricsEnabled() || - (Debug.isEnabled() && areScopedGlobalMetricsEnabled()) || (Debug.isEnabled() && Debug.isMethodFilteringEnabled())) { + (Debug.isEnabled() && areScopedGlobalMetricsEnabled(options)) || (Debug.isEnabled() && Debug.isMethodFilteringEnabled())) { // This must be created here to avoid loading the DebugValuesPrinter class // during shutdown() which in turn can cause a deadlock int mmPrinterType = 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue() ? 1 : 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterFile.getValue() != null ? 2 : 0; + mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue(options) ? 1 : 0; + mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterFile.getValue(options) != null ? 2 : 0; switch (mmPrinterType) { case 0: debugValuesPrinter = new DebugValuesPrinter(); @@ -188,22 +215,33 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { // Complete initialization of backends try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { - hostBackend.completeInitialization(jvmciRuntime); + hostBackend.completeInitialization(jvmciRuntime, options); } - for (HotSpotBackend backend : backends.values()) { + for (HotSpotBackend backend : backends.getValues()) { if (backend != hostBackend) { try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) { - backend.completeInitialization(jvmciRuntime); + backend.completeInitialization(jvmciRuntime, options); } } } - BenchmarkCounters.initialize(jvmciRuntime); + BenchmarkCounters.initialize(jvmciRuntime, options); assert checkArrayIndexScaleInvariants(); runtimeStartTime = System.nanoTime(); bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class); + + assert checkPathIsInvalid(DELETED_OUTPUT_DIRECTORY); + } + + private static boolean checkPathIsInvalid(String path) { + try { + Paths.get(path); + return false; + } catch (InvalidPathException e) { + return true; + } } private HotSpotBackend registerBackend(HotSpotBackend backend) { @@ -223,20 +261,38 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { return config; } + @Override + public OptionValues getOptions() { + return mBean.optionsFor(options, null); + } + + @Override + public OptionValues getOptions(ResolvedJavaMethod forMethod) { + return mBean.optionsFor(options, forMethod); + } + + @Override + public Group createSnippetCounterGroup(String name) { + if (snippetCounterGroups != null) { + Group group = new Group(name); + snippetCounterGroups.add(group); + return group; + } + return null; + } + @Override public String getName() { return getClass().getSimpleName(); } - private final NodeCollectionsProvider nodeCollectionsProvider = new DefaultNodeCollectionsProvider(); - @SuppressWarnings("unchecked") @Override public T getCapability(Class clazz) { if (clazz == RuntimeProvider.class) { return (T) this; - } else if (clazz == CollectionsProvider.class || clazz == NodeCollectionsProvider.class) { - return (T) nodeCollectionsProvider; + } else if (clazz == OptionValues.class) { + return (T) options; } else if (clazz == StackIntrospection.class) { return (T) this; } else if (clazz == SnippetReflectionProvider.class) { @@ -258,29 +314,35 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { return backends.get(arch); } - public Map, HotSpotBackend> getBackends() { - return Collections.unmodifiableMap(backends); - } - private long runtimeStartTime; + private boolean shutdown; /** * Take action related to entering a new execution phase. * * @param phase the execution phase being entered */ - static void phaseTransition(String phase) { - CompilationStatistics.clear(phase); + void phaseTransition(String phase) { + if (Options.UseCompilationStatistics.getValue(options)) { + CompilationStatistics.clear(phase); + } } void shutdown() { + shutdown = true; if (debugValuesPrinter != null) { - debugValuesPrinter.printDebugValues(); + debugValuesPrinter.printDebugValues(options); } phaseTransition("final"); - SnippetCounter.printGroups(TTY.out().out()); - BenchmarkCounters.shutdown(runtime(), runtimeStartTime); + if (snippetCounterGroups != null) { + for (Group group : snippetCounterGroups) { + TTY.out().out().println(group); + } + } + BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime); + + archiveAndDeleteOutputDirectory(); } void clearMeters() { @@ -300,4 +362,106 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { public boolean isBootstrapping() { return bootstrapJVMCI && !bootstrapFinished; } + + @Override + public boolean isShutdown() { + return shutdown; + } + + /** + * Gets a unique identifier for this execution such as a process ID. + */ + private static String getExecutionID() { + String runtimeName = 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; + } + + private String outputDirectory; + + /** + * Use an illegal file name to denote that the output directory has been deleted. + */ + private static final String DELETED_OUTPUT_DIRECTORY = "\u0000"; + + @Override + public String getOutputDirectory() { + return getOutputDirectory(true); + } + + private synchronized String getOutputDirectory(boolean createIfNull) { + if (outputDirectory == null && createIfNull) { + outputDirectory = "graal_output_" + getExecutionID(); + File dir = new File(outputDirectory).getAbsoluteFile(); + if (!dir.exists()) { + dir.mkdirs(); + if (!dir.exists()) { + TTY.println("Warning: could not create Graal diagnostic directory " + dir); + return null; + } + } + } + return DELETED_OUTPUT_DIRECTORY.equals(outputDirectory) ? null : outputDirectory; + } + + /** + * Archives and deletes the {@linkplain #getOutputDirectory() output directory} if it exists. + */ + private void archiveAndDeleteOutputDirectory() { + String outDir = getOutputDirectory(false); + if (outDir != null) { + Path dir = Paths.get(outDir); + if (dir.toFile().exists()) { + try { + // Give compiler threads a chance to finishing dumping + Thread.sleep(1000); + } catch (InterruptedException e1) { + } + File zip = new File(outDir + ".zip").getAbsoluteFile(); + List toDelete = new ArrayList<>(); + try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) { + zos.setLevel(Deflater.BEST_COMPRESSION); + Files.walkFileTree(dir, Collections.emptySet(), Integer.MAX_VALUE, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (attrs.isRegularFile()) { + ZipEntry ze = new ZipEntry(file.toString()); + zos.putNextEntry(ze); + zos.write(Files.readAllBytes(file)); + zos.closeEntry(); + } + toDelete.add(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path d, IOException exc) throws IOException { + toDelete.add(d); + return FileVisitResult.CONTINUE; + } + }); + TTY.println("Graal diagnostic output saved in %s", zip); + } catch (IOException e) { + TTY.printf("IO error archiving %s:%n", dir); + e.printStackTrace(TTY.out); + } + for (Path p : toDelete) { + try { + Files.delete(p); + } catch (IOException e) { + TTY.printf("IO error deleting %s:%n", p); + e.printStackTrace(TTY.out); + } + } + } + outputDirectory = DELETED_OUTPUT_DIRECTORY; + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java index f662ab8757c..a634ad8178c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java @@ -24,16 +24,19 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.api.runtime.GraalRuntime; 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 /** * Configuration information for the HotSpot Graal runtime. */ -public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvider { +public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvider, Group.Factory { default TargetDescription getTarget() { return getHostBackend().getTarget(); @@ -51,8 +54,38 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid GraalHotSpotVMConfig getVMConfig(); + /** + * Gets the option values associated with this runtime. + */ + OptionValues getOptions(); + + /** + * Gets the option values associated with this runtime that are applicable for given method. + * + * @param forMethod the method we are seeking for options for + * @return the options - by default same as {@link #getOptions()} + */ + default OptionValues getOptions(ResolvedJavaMethod forMethod) { + return getOptions(); + } + /** * Determines if the VM is currently bootstrapping the JVMCI compiler. */ boolean isBootstrapping(); + + /** + * This runtime has been requested to shutdown. + */ + boolean isShutdown(); + + /** + * Gets a directory into which diagnostics such crash reports and dumps should be written. This + * method will create the directory if it doesn't exist so it should only be called if + * diagnostics are about to be generated. + * + * @return the directory into which diagnostics can be written or {@code null} if the directory + * does not exist and could not be created or has already been deleted + */ + String getOutputDirectory(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java index 64d1073e80a..2f0dcab052b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java @@ -22,21 +22,29 @@ */ package org.graalvm.compiler.hotspot; -import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.GraalDebugConfig; - import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotVMEventListener; +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.serviceprovider.GraalServices; + +import java.util.ArrayList; +import java.util.List; public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { private final HotSpotGraalRuntime runtime; + private List listeners; HotSpotGraalVMEventListener(HotSpotGraalRuntime runtime) { this.runtime = runtime; + listeners = new ArrayList<>(); + for (HotSpotCodeCacheListener listener : GraalServices.load(HotSpotCodeCacheListener.class)) { + listeners.add(listener); + } } @Override @@ -46,20 +54,23 @@ public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { @Override public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { + if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) { CompilationResult compResult = Debug.contextLookup(CompilationResult.class); assert compResult != null : "can't dump installed code properly without CompilationResult"; - Debug.dump(Debug.BASIC_LOG_LEVEL, installedCode, "After code installation"); + Debug.dump(Debug.BASIC_LEVEL, installedCode, "After code installation"); } if (Debug.isLogEnabled()) { Debug.log("%s", codeCache.disassemble(installedCode)); } + for (HotSpotCodeCacheListener listener : listeners) { + listener.notifyInstall(codeCache, installedCode, compiledCode); + } } @Override public void notifyBootstrapFinished() { runtime.notifyBootstrapFinished(); - if (GraalDebugConfig.Options.ClearMetricsAfterBootstrap.getValue()) { + if (GraalDebugConfig.Options.ClearMetricsAfterBootstrap.getValue(runtime.getOptions())) { runtime.clearMeters(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java index 8df8a9c82ae..93505051c2a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java @@ -22,19 +22,20 @@ */ package org.graalvm.compiler.hotspot; +import static jdk.vm.ci.code.CodeUtil.K; import static jdk.vm.ci.code.CodeUtil.getCallingConvention; import static jdk.vm.ci.common.InitTimer.timer; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; import org.graalvm.compiler.hotspot.stubs.Stub; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.common.InitTimer; @@ -49,16 +50,12 @@ import jdk.vm.ci.runtime.JVMCICompiler; public abstract class HotSpotHostBackend extends HotSpotBackend { /** - * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()} or - * {@link DeoptimizationStub#deoptimizationHandler} depending on - * {@link HotSpotBackend.Options#PreferGraalStubs}. + * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()}. */ public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptHandler", void.class); /** - * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()} or - * {@link UncommonTrapStub#uncommonTrapHandler} depending on - * {@link HotSpotBackend.Options#PreferGraalStubs}. + * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()}. */ public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class); @@ -71,16 +68,16 @@ public abstract class HotSpotHostBackend extends HotSpotBackend { @Override @SuppressWarnings("try") - public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime) { + public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { final HotSpotProviders providers = getProviders(); HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); try (InitTimer st = timer("foreignCalls.initialize")) { - foreignCalls.initialize(providers); + foreignCalls.initialize(providers, options); } try (InitTimer st = timer("lowerer.initialize")) { - lowerer.initialize(providers, config); + lowerer.initialize(options, providers, config); } } @@ -114,7 +111,7 @@ public abstract class HotSpotHostBackend extends HotSpotBackend { // is greater than a page. int pageSize = config.vmPageSize; - int bangEnd = config.stackShadowPages * pageSize; + int bangEnd = NumUtil.roundUp(config.stackShadowPages * 4 * K, pageSize); // This is how far the previous frame's stack banging extended. int bangEndSafe = bangEnd; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java index 8b91390bfb9..a0d05bd48df 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot; -import java.util.List; +import java.util.ArrayList; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.InstructionCounter; @@ -80,7 +80,7 @@ public class HotSpotInstructionProfiling extends PostAllocationOptimizationPhase } public void doBlock(AbstractBlockBase block) { - List instructions = lir.getLIRforBlock(block); + ArrayList instructions = lir.getLIRforBlock(block); assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java index 11383b77a7c..f3543dd8fed 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.hotspot; -import java.util.Map; - -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; @@ -32,6 +29,8 @@ import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; @@ -52,14 +51,14 @@ public class HotSpotLIRGenerationResult extends LIRGenerationResult { * Map from debug infos that need to be updated with callee save information to the operations * that provide the information. */ - private Map calleeSaveInfo = CollectionsFactory.newMap(); + private EconomicMap calleeSaveInfo = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE); public HotSpotLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, CallingConvention callingConvention, Object stub) { super(compilationId, lir, frameMapBuilder, callingConvention); this.stub = stub; } - public Map getCalleeSaveInfo() { + public EconomicMap getCalleeSaveInfo() { return calleeSaveInfo; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java index f2f45e24fec..199d51f58c7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java @@ -26,22 +26,13 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode; -import org.graalvm.compiler.hotspot.nodes.EnterUnpackFramesStackFrameNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; -import org.graalvm.compiler.hotspot.nodes.LeaveCurrentStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveDeoptimizedStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.PushInterpreterFrameNode; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; import org.graalvm.compiler.hotspot.nodes.profiling.RandomSeedNode; import org.graalvm.compiler.hotspot.replacements.EncodedSymbolConstant; import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -70,65 +61,6 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason); - /** - * Emits code for a {@link SaveAllRegistersNode}. - * - * @return a {@link SaveRegistersOp} operation - */ - SaveRegistersOp emitSaveAllRegisters(); - - /** - * Emits code for a {@link LeaveCurrentStackFrameNode}. - * - * @param saveRegisterOp saved registers - */ - default void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link LeaveDeoptimizedStackFrameNode}. - * - * @param frameSize - * @param initialInfo - */ - default void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link EnterUnpackFramesStackFrameNode}. - * - * @param framePc - * @param senderSp - * @param senderFp - * @param saveRegisterOp - */ - default void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link LeaveUnpackFramesStackFrameNode}. - * - * @param saveRegisterOp - */ - default void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link PushInterpreterFrameNode}. - * - * @param frameSize - * @param framePc - * @param senderSp - * @param initialInfo - */ - default void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - throw GraalError.unimplemented(); - } - /** * Emits code for a {@link LoadConstantIndirectlyNode}. * @@ -227,29 +159,6 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { throw GraalError.unimplemented(); } - /** - * Emits code for a {@link UncommonTrapCallNode}. - * - * @param trapRequest - * @param mode - * @param saveRegisterOp - * @return a {@code Deoptimization::UnrollBlock} pointer - */ - default Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link DeoptimizationFetchUnrollInfoCallNode}. - * - * @param mode - * @param saveRegisterOp - * @return a {@code Deoptimization::UnrollBlock} pointer - */ - default Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - /** * Gets a stack slot for a lock at a given lock nesting depth. */ @@ -258,8 +167,4 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { @Override HotSpotProviders getProviders(); - Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull); - - Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java index 7dc534a29a9..9b0dd3cfcbf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java @@ -23,9 +23,8 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.core.match.MatchableNode; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.lir.gen.LIRGenerator; +import org.graalvm.compiler.nodes.CompressionNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -43,7 +42,4 @@ public interface HotSpotNodeLIRBuilder { } void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc); - - void visitDirectCompareAndSwap(DirectCompareAndSwapNode x); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java index a8b7982ebf4..97fc0fd01ed 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java @@ -29,7 +29,7 @@ import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.ArrayList; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; @@ -104,7 +104,7 @@ public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder { LIRKind kind = (LIRKind) obj.getValueKind(); int bytes = bytesPerElement(kind); if (kind.isUnknownReference()) { - throw GraalError.shouldNotReachHere("unknown reference alive across safepoint"); + throw GraalError.shouldNotReachHere(String.format("unknown reference alive across safepoint: %s", obj)); } else { Location base = null; if (kind.isDerivedReference()) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index dc52af69b7a..e1e265de8d1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.hotspot.word.HotSpotOperation; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.ReplacementsImpl; @@ -37,8 +38,8 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class HotSpotReplacementsImpl extends ReplacementsImpl { - public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { - super(providers, snippetReflection, bytecodeProvider, target); + public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + super(options, providers, snippetReflection, bytecodeProvider, target); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotRetryableCompilation.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotRetryableCompilation.java new file mode 100644 index 00000000000..7d0d79ba9ca --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotRetryableCompilation.java @@ -0,0 +1,166 @@ +/* + * 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 static org.graalvm.compiler.debug.Debug.VERBOSE_LEVEL; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.DUMP_METHOD; +import static org.graalvm.compiler.debug.DelegatingDebugConfig.Level.DUMP; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DumpPath; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.ForceDebugEnable; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintCFGFileName; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.PrintGraphFileName; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.nio.file.InvalidPathException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; + +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugDumpHandler; +import org.graalvm.compiler.debug.DebugRetryableTask; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugConfigCustomizer; + +import jdk.vm.ci.code.BailoutException; + +/** + * Utility for retrying a compilation that throws an exception where the retry enables extra logging + * for subsequently diagnosing the failure. + */ +public abstract class HotSpotRetryableCompilation extends DebugRetryableTask { + + protected final OptionValues originalOptions; + protected final HotSpotGraalRuntimeProvider runtime; + + public HotSpotRetryableCompilation(HotSpotGraalRuntimeProvider runtime, OptionValues options) { + this.runtime = runtime; + this.originalOptions = options; + } + + /** + * Gets a value that represents the compilation unit being compiled. + */ + @Override + public abstract String toString(); + + private static String sanitizedFileName(String name) { + StringBuilder buf = new StringBuilder(name.length()); + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + try { + Paths.get(String.valueOf(c)); + } catch (InvalidPathException e) { + buf.append('_'); + } + buf.append(c); + } + return buf.toString(); + } + + @Override + protected boolean onRetry(Throwable t) { + if (t instanceof BailoutException) { + return false; + } + + if (!Debug.isEnabled()) { + TTY.printf("Error while compiling %s due to %s.%nRe-run with -D%s%s=true to capture graph dumps upon a compilation failure.%n", this, + t, HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX, ForceDebugEnable.getName()); + return false; + } + + if (Dump.hasBeenSet(originalOptions)) { + // If dumping is explicitly enabled, Graal is being debugged + // so don't interfere with what the user is expecting to see. + return false; + } + + String outputDirectory = runtime.getOutputDirectory(); + if (outputDirectory == null) { + return false; + } + String dumpName = sanitizedFileName(toString()); + File dumpPath = new File(outputDirectory, dumpName); + dumpPath.mkdirs(); + if (!dumpPath.exists()) { + TTY.println("Warning: could not create dump directory " + dumpPath); + return false; + } + + TTY.println("Retrying compilation of " + this + " due to " + t); + retryLogPath = new File(dumpPath, "retry.log").getPath(); + log("Exception causing retry", t); + retryDumpHandlers = new ArrayList<>(); + retryOptions = new OptionValues(originalOptions, + PrintCFGFileName, dumpName, + PrintGraphFileName, dumpName, + DumpPath, dumpPath.getPath()); + override(DUMP, VERBOSE_LEVEL).enable(DUMP_METHOD); + new GraalDebugConfigCustomizer().customize(this); + return true; + } + + private Collection retryDumpHandlers; + private OptionValues retryOptions; + private String retryLogPath; + + /** + * Prints a message to a retry log file. + * + * @param message the message to print + * @param t if non-{@code null}, the stack trace for this exception is written to the retry log + * after {@code message} + */ + protected void log(String message, Throwable t) { + if (retryLogPath != null) { + try (PrintStream retryLog = new PrintStream(new FileOutputStream(retryLogPath), true)) { + StringBuilder buf = new StringBuilder(Thread.currentThread() + ": " + message); + if (t != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + t.printStackTrace(new PrintStream(baos)); + buf.append(System.lineSeparator()).append(baos.toString()); + } + retryLog.println(buf); + } catch (FileNotFoundException e) { + TTY.println("Warning: could not open retry log file " + retryLogPath + " [" + e + "]"); + } + } + } + + @Override + public Collection dumpHandlers() { + return retryDumpHandlers; + } + + @Override + public OptionValues getOptions() { + return retryOptions; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java index 8bd1710f9e7..0a8fe40f6f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + import java.io.PrintStream; import org.graalvm.compiler.debug.TTYStreamProvider; @@ -36,13 +38,13 @@ public class HotSpotTTYStreamProvider implements TTYStreamProvider { // @formatter:off @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying " + - "the process, usually the process id and %t will be replaced by System.currentTimeMillis().", type = OptionType.Expert) - public static final PrintStreamOption LogFile = new PrintStreamOption(); + "the process, usually the process id and %t will be replaced by System.currentTimeMillis().", type = OptionType.Expert) + public static final PrintStreamOptionKey LogFile = new PrintStreamOptionKey(); // @formatter:on } @Override public PrintStream getStream() { - return Options.LogFile.getStream(); + return Options.LogFile.getStream(HOTSPOT_OPTIONS); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java index abae7a39549..ea72b7342c4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.hotspot; import java.util.Formatter; +import java.util.Objects; /** * Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API @@ -37,10 +38,11 @@ import java.util.Formatter; class JVMCIVersionCheck { private static final int JVMCI8_MIN_MAJOR_VERSION = 0; - private static final int JVMCI8_MIN_MINOR_VERSION = 23; + private static final int JVMCI8_MIN_MINOR_VERSION = 26; - // Will be updated once an ea build with the required JVMCI API is available. - private static final int JVMCI9_MIN_EA_BUILD = 143; + // MAX_VALUE indicates that no current EA version is compatible with Graal. + // Note: Keep README.md in sync with the EA version support checked here. + private static final int JVMCI9_MIN_EA_BUILD = 168; private static void failVersionCheck(boolean exit, String reason, Object... args) { Formatter errorMessage = new Formatter().format(reason, args); @@ -77,13 +79,27 @@ class JVMCIVersionCheck { start += "-jvmci-".length(); int end = vmVersion.indexOf('.', start); if (end > 0) { - int major = Integer.parseInt(vmVersion.substring(start, end)); + int major; + try { + major = Integer.parseInt(vmVersion.substring(start, end)); + } catch (NumberFormatException e) { + failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion); + return; + } start = end + 1; end = start; while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) { end++; } - int minor = Integer.parseInt(vmVersion.substring(start, end)); + int minor; + try { + minor = Integer.parseInt(vmVersion.substring(start, end)); + } catch (NumberFormatException e) { + failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JVMCI minor version from java.vm.version property: %s.%n", vmVersion); + return; + } if (major >= JVMCI8_MIN_MAJOR_VERSION && minor >= JVMCI8_MIN_MINOR_VERSION) { return; } @@ -112,11 +128,22 @@ class JVMCIVersionCheck { while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) { end++; } - int build = Integer.parseInt(vmVersion.substring(start, end)); + int build; + try { + build = Integer.parseInt(vmVersion.substring(start, end)); + } catch (NumberFormatException e) { + failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JDK9 EA build number from java.vm.version property: %s.%n", vmVersion); + return; + } if (build >= JVMCI9_MIN_EA_BUILD) { return; } - failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD); + if (Objects.equals(JVMCI9_MIN_EA_BUILD, Integer.MAX_VALUE)) { + failVersionCheck(exitOnFailure, "This version of Graal is not compatible with any JDK 9 Early Access build.%n"); + } else { + failVersionCheck(exitOnFailure, "The VM is an insufficiently recent EA JDK9 build for Graal: %d < %d.%n", build, JVMCI9_MIN_EA_BUILD); + } return; } failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java new file mode 100644 index 00000000000..ad48b0e2956 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java @@ -0,0 +1,240 @@ +/* + * 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.hotspot; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import java.util.stream.Collectors; + +import org.graalvm.compiler.debug.CSVUtil; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; +import org.graalvm.compiler.nodes.spi.Virtualizable; + +public class NodeCostDumpUtil { + + private static final String prefix1 = "com.oracle."; + private static final String prefix2 = "org.graalvm."; + private static final String FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s"); + + private static String getArgumentRegex(String arg) { + if (arg.length() == 0) { + return null; + } + try { + Pattern.compile(arg); + return arg; + } catch (PatternSyntaxException e) { + // silently ignore + System.err.println("Invalid regex given, defaulting to \".*\" regex.."); + return null; + } + } + + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("NodeCostDumpUtil expects exactly one argument, the node name regex to match against."); + System.exit(-1); + } + final String pattern = getArgumentRegex(args[0]); + String version = System.getProperty("java.specification.version"); + if (version.compareTo("1.9") >= 0) { + System.err.printf("NodeCostDumpUtil does not support JDK versions greater than 1.8, current version is %s.\n", version); + System.exit(-1); + } + String[] jvmciCP = System.getProperty("jvmci.class.path.append").split(File.pathSeparator); + String[] primarySuiteCP = System.getProperty("primary.suite.cp").split(File.pathSeparator); + ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); + HashSet> classes = new HashSet<>(); + try { + Set uniquePaths = new HashSet<>(Arrays.asList(primarySuiteCP)); + uniquePaths.addAll(Arrays.asList(jvmciCP)); + for (String path : uniquePaths) { + if (new File(path).exists()) { + if (path.endsWith(".jar")) { + try (FileSystem jarFileSystem = FileSystems.newFileSystem(URI.create("jar:file:" + path), Collections.emptyMap())) { + initAllClasses(jarFileSystem.getPath("/"), applicationClassLoader, classes); + } + } else { + initAllClasses(FileSystems.getDefault().getPath(path), applicationClassLoader, classes); + } + } + } + } catch (IOException ex) { + GraalError.shouldNotReachHere(); + } + System.err.printf("Loaded %d classes...\n", classes.size()); + List> nodeClasses = new ArrayList<>(); + for (Class loaded : classes) { + if (Node.class.isAssignableFrom(loaded) && !loaded.isArray()) { + nodeClasses.add(loaded); + } + } + System.err.printf("Loaded %s node classes...\n", nodeClasses.size()); + List> nc = new ArrayList<>(); + for (Class nodeClass : nodeClasses) { + Field f; + try { + f = nodeClass.getField("TYPE"); + f.setAccessible(true); + Object val = f.get(null); + NodeClass nodeType = (NodeClass) val; + nc.add(nodeType); + } catch (Throwable t) { + // Silently ignore problems here + } + } + System.err.printf("Read TYPE field from %s node classes...\n", nc.size()); + nc = nc.stream().filter(x -> x != null).collect(Collectors.toList()); + nc.sort((x, y) -> { + String a = x.getJavaClass().getName(); + String b = y.getJavaClass().getName(); + return a.compareTo(b); + }); + CSVUtil.Escape.println(System.out, FMT, "NodeName", "Size", "Overrides Size Method", "Cycles", "Overrides Cycles Method", "Canonicalizable", "MemoryCheckPoint", "Virtualizable"); + for (NodeClass nodeclass : nc) { + String packageStrippedName = null; + try { + packageStrippedName = nodeclass.getJavaClass().getCanonicalName().replace(prefix1, "").replace(prefix2, ""); + } catch (Throwable t) { + // do nothing + continue; + } + if (pattern != null && !packageStrippedName.matches(pattern)) { + continue; + } + boolean overridesSizeMethod = false; + boolean overridesCyclesMethod = false; + Class c = nodeclass.getJavaClass(); + try { + c.getDeclaredMethod("estimatedNodeSize"); + overridesSizeMethod = true; + } catch (Throwable t) { + // do nothing + } + try { + c.getDeclaredMethod("estimatedNodeCycles"); + overridesCyclesMethod = true; + } catch (Throwable t) { + // do nothing + } + CSVUtil.Escape.println(System.out, FMT, packageStrippedName, nodeclass.size(), overridesSizeMethod, nodeclass.cycles(), overridesCyclesMethod, canonicalizable(c), memoryCheckPoint(c), + virtualizable(c)); + } + } + + private static boolean canonicalizable(Class c) { + return Canonicalizable.class.isAssignableFrom(c); + } + + private static boolean virtualizable(Class c) { + return Virtualizable.class.isAssignableFrom(c); + } + + private static boolean memoryCheckPoint(Class c) { + return MemoryCheckpoint.class.isAssignableFrom(c); + } + + private static void initAllClasses(final Path root, ClassLoader classLoader, HashSet> classes) { + try { + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String className = root.relativize(file).toString(); + ClassLoader c = classLoader; + if (className.endsWith(".class")) { + String prefix = prefixed(className); + if (prefix != null) { + String stripped = stripClassName(className); + c = new URLClassLoader(new URL[]{new File(constructURLPart(stripped, className, prefix)).toURI().toURL()}, classLoader); + className = constructClazzPart(stripped, prefix); + } else { + String clazzPart = className.replace('/', '.'); + className = clazzPart.substring(0, clazzPart.length() - ".class".length()); + } + try { + Class systemClass = Class.forName(className, false, c); + if (systemClass.getEnclosingClass() != null) { + try { + classes.add(systemClass.getEnclosingClass()); + } catch (Throwable t) { + // do nothing + } + } + classes.add(systemClass); + } catch (Throwable ignored) { + } + } + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException ex) { + GraalError.shouldNotReachHere(); + } + } + + private static String prefixed(String className) { + if (className.contains(prefix1) && className.indexOf(prefix1) > 0) { + return prefix1; + } else if (className.contains(prefix2) && className.indexOf(prefix2) > 0) { + return prefix2; + } + return null; + } + + private static String stripClassName(String className) { + return className.replace('/', '.'); + } + + private static String constructClazzPart(String stripped, String prefix) { + String clazzPart = stripped.substring(stripped.lastIndexOf(prefix), stripped.length()); + return clazzPart.substring(0, clazzPart.length() - ".class".length()); + } + + private static String constructURLPart(String stripped, String className, String prefix) { + return className.substring(0, stripped.lastIndexOf(prefix)); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java similarity index 58% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java index e2b389f8b96..a56704c4ac9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java @@ -28,10 +28,9 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.UniquePathUtilities; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -39,32 +38,20 @@ import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; /** * An option that encapsulates and configures a print stream. */ -public class PrintStreamOption extends OptionValue { +public class PrintStreamOptionKey extends OptionKey { - public PrintStreamOption() { + public PrintStreamOptionKey() { super(null); } /** - * The print stream to which output will be written. - * - * Declared {@code volatile} to enable safe use of double-checked locking in - * {@link #getStream()} and {@link #setValue(Object)}. - */ - private volatile PrintStream ps; - - /** - * Replaces any instance of %p with an identifying name such as a process ID extracted from - * {@link RuntimeMXBean#getName()} and any instance of %t with the value of - * {@link System#currentTimeMillis()}. + * 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 */ - private String getFilename() { - String name = getValue(); - if (name.contains("%t")) { - name = name.replaceAll("%t", String.valueOf(UniquePathUtilities.getGlobalTimeStamp())); - } + private String getFilename(OptionValues options) { + String name = getValue(options); if (name.contains("%p")) { String runtimeName = ManagementFactory.getRuntimeMXBean().getName(); try { @@ -126,45 +113,26 @@ public class PrintStreamOption extends OptionValue { * Gets the print stream configured by this option. If no file is configured, the print stream * will output to HotSpot's {@link HotSpotJVMCIRuntimeProvider#getLogStream() log} stream. */ - public PrintStream getStream() { - if (ps == null) { - if (getValue() != null) { - synchronized (this) { - if (ps == null) { - try { - final boolean enableAutoflush = true; - ps = new PrintStream(new FileOutputStream(getFilename()), enableAutoflush); - /* - * Add the JVM and Java arguments to the log file to help identity it. - */ - String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments()); - ps.println("VM Arguments: " + inputArguments); - String cmd = System.getProperty("sun.java.command"); - if (cmd != null) { - ps.println("sun.java.command=" + cmd); - } - } catch (FileNotFoundException e) { - throw new RuntimeException("couldn't open file: " + getValue(), e); - } - } + public PrintStream getStream(OptionValues options) { + if (getValue(options) != null) { + try { + final boolean enableAutoflush = true; + PrintStream ps = new PrintStream(new FileOutputStream(getFilename(options)), enableAutoflush); + /* + * Add the JVM and Java arguments to the log file to help identity it. + */ + String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments()); + ps.println("VM Arguments: " + inputArguments); + String cmd = System.getProperty("sun.java.command"); + if (cmd != null) { + ps.println("sun.java.command=" + cmd); } - } else { - ps = new PrintStream(new DelayedOutputStream()); + return ps; + } catch (FileNotFoundException e) { + throw new RuntimeException("couldn't open file: " + getValue(options), e); } + } else { + return new PrintStream(new DelayedOutputStream()); } - return ps; - } - - @Override - public void setValue(Object v) { - if (ps != null) { - synchronized (this) { - if (ps != null) { - ps.close(); - ps = null; - } - } - } - super.setValue(v); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java index 700fa99e65f..ada3106e7d4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java @@ -46,9 +46,9 @@ import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.UniquePathUtilities; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -93,26 +93,26 @@ public class BenchmarkCounters { //@formatter:off @Option(help = "Turn on the benchmark counters, and displays the results on VM shutdown", type = OptionType.Debug) - public static final OptionValue GenericDynamicCounters = new OptionValue<>(false); + public static final OptionKey GenericDynamicCounters = new OptionKey<>(false); @Option(help = "Turn on the benchmark counters, and displays the results every n milliseconds", type = OptionType.Debug) - public static final OptionValue TimedDynamicCounters = new OptionValue<>(-1); + public static final OptionKey TimedDynamicCounters = new OptionKey<>(-1); @Option(help = "Turn on the benchmark counters, and listen for specific patterns on System.out/System.err:%n" + "Format: (err|out),start pattern,end pattern (~ matches multiple digits)%n" + "Examples:%n" + " dacapo = 'err, starting =====, PASSED in'%n" + " specjvm2008 = 'out,Iteration ~ (~s) begins:,Iteration ~ (~s) ends:'", type = OptionType.Debug) - public static final OptionValue BenchmarkDynamicCounters = new OptionValue<>(null); + public static final OptionKey BenchmarkDynamicCounters = new OptionKey<>(null); @Option(help = "Use grouping separators for number printing", type = OptionType.Debug) - public static final OptionValue DynamicCountersPrintGroupSeparator = new OptionValue<>(true); + public static final OptionKey DynamicCountersPrintGroupSeparator = new OptionKey<>(true); @Option(help = "Print in human readable format", type = OptionType.Debug) - public static final OptionValue DynamicCountersHumanReadable = new OptionValue<>(true); + public static final OptionKey DynamicCountersHumanReadable = new OptionKey<>(true); @Option(help = "Benchmark counters log file (default is stdout)", type = OptionType.Debug) - public static final OptionValue BenchmarkCountersFile = new OptionValue<>(null); + public static final OptionKey BenchmarkCountersFile = new OptionKey<>(null); @Option(help = "Dump dynamic counters", type = OptionType.Debug) - public static final StableOptionValue BenchmarkCountersDumpDynamic = new StableOptionValue<>(true); + public static final OptionKey BenchmarkCountersDumpDynamic = new OptionKey<>(true); @Option(help = "Dump static counters", type = OptionType.Debug) - public static final StableOptionValue BenchmarkCountersDumpStatic = new StableOptionValue<>(false); + public static final OptionKey BenchmarkCountersDumpStatic = new OptionKey<>(false); //@formatter:on } @@ -168,24 +168,24 @@ public class BenchmarkCounters { return counter; } - private static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) { + private static synchronized void dump(OptionValues options, PrintStream out, double seconds, long[] counters, int maxRows) { if (!counterMap.isEmpty()) { - if (Options.DynamicCountersHumanReadable.getValue()) { + if (Options.DynamicCountersHumanReadable.getValue(options)) { out.println("====== dynamic counters (" + counterMap.size() + " in total) ======"); } TreeSet set = new TreeSet<>(); counterMap.forEach((nameGroup, counter) -> set.add(counter.group)); for (String group : set) { if (group != null) { - if (Options.BenchmarkCountersDumpStatic.getValue()) { - dumpCounters(out, seconds, counters, true, group, maxRows); + if (Options.BenchmarkCountersDumpStatic.getValue(options)) { + dumpCounters(options, out, seconds, counters, true, group, maxRows); } - if (Options.BenchmarkCountersDumpDynamic.getValue()) { - dumpCounters(out, seconds, counters, false, group, maxRows); + if (Options.BenchmarkCountersDumpDynamic.getValue(options)) { + dumpCounters(options, out, seconds, counters, false, group, maxRows); } } } - if (Options.DynamicCountersHumanReadable.getValue()) { + if (Options.DynamicCountersHumanReadable.getValue(options)) { out.println("============================"); } @@ -197,7 +197,7 @@ public class BenchmarkCounters { delta = counters; } - private static synchronized void dumpCounters(PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) { + private static synchronized void dumpCounters(OptionValues options, PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) { // collect the numbers long[] array; @@ -213,8 +213,8 @@ public class BenchmarkCounters { } } Set> counterEntrySet = counterMap.entrySet(); - if (Options.DynamicCountersHumanReadable.getValue()) { - dumpHumanReadable(out, seconds, staticCounter, group, maxRows, array, counterEntrySet); + if (Options.DynamicCountersHumanReadable.getValue(options)) { + dumpHumanReadable(options, out, seconds, staticCounter, group, maxRows, array, counterEntrySet); } else { dumpComputerReadable(out, staticCounter, group, array, counterEntrySet); } @@ -224,7 +224,8 @@ public class BenchmarkCounters { return nameGroup.substring(0, nameGroup.length() - group.length() - 1); } - private static void dumpHumanReadable(PrintStream out, double seconds, boolean staticCounter, String group, int maxRows, long[] array, Set> counterEntrySet) { + private static void dumpHumanReadable(OptionValues options, PrintStream out, double seconds, boolean staticCounter, String group, int maxRows, long[] array, + Set> counterEntrySet) { // sort the counters by putting them into a sorted map TreeMap sorted = new TreeMap<>(); long sum = 0; @@ -252,7 +253,7 @@ public class BenchmarkCounters { cnt--; } - String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue() ? "%,19d" : "%19d"; + String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue(options) ? "%,19d" : "%19d"; if (staticCounter) { out.println("=========== " + group + " (static counters):"); for (Map.Entry entry : sorted.entrySet()) { @@ -348,7 +349,7 @@ public class BenchmarkCounters { } } - public static void initialize(final HotSpotJVMCIRuntime jvmciRuntime) { + public static void initialize(final HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { final class BenchmarkCountersOutputStream extends CallbackOutputStream { private long startTime; @@ -376,15 +377,15 @@ public class BenchmarkCounters { if (waitingForEnd) { waitingForEnd = false; running = false; - BenchmarkCounters.dump(getPrintStream(), (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + BenchmarkCounters.dump(options, getPrintStream(options), (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); } break; } } } - if (Options.BenchmarkDynamicCounters.getValue() != null) { - String[] arguments = Options.BenchmarkDynamicCounters.getValue().split(","); + if (Options.BenchmarkDynamicCounters.getValue(options) != null) { + String[] arguments = Options.BenchmarkDynamicCounters.getValue(options).split(","); if (arguments.length == 0 || (arguments.length % 3) != 0) { throw new GraalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)"); } @@ -399,23 +400,23 @@ public class BenchmarkCounters { } enabled = true; } - if (Options.GenericDynamicCounters.getValue()) { + if (Options.GenericDynamicCounters.getValue(options)) { enabled = true; } - if (Options.TimedDynamicCounters.getValue() > 0) { + if (Options.TimedDynamicCounters.getValue(options) > 0) { Thread thread = new Thread() { long lastTime = System.nanoTime(); - PrintStream out = getPrintStream(); + PrintStream out = getPrintStream(options); @Override public void run() { while (true) { try { - Thread.sleep(Options.TimedDynamicCounters.getValue()); + Thread.sleep(Options.TimedDynamicCounters.getValue(options)); } catch (InterruptedException e) { } long time = System.nanoTime(); - dump(out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); + dump(options, out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); lastTime = time; } } @@ -430,16 +431,16 @@ public class BenchmarkCounters { } } - public static void shutdown(HotSpotJVMCIRuntime jvmciRuntime, long compilerStartTime) { - if (Options.GenericDynamicCounters.getValue()) { - dump(getPrintStream(), (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + public static void shutdown(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options, long compilerStartTime) { + if (Options.GenericDynamicCounters.getValue(options)) { + dump(options, getPrintStream(options), (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); } } - private static PrintStream getPrintStream() { - if (Options.BenchmarkCountersFile.getValue() != null) { + private static PrintStream getPrintStream(OptionValues options) { + if (Options.BenchmarkCountersFile.getValue(options) != null) { try { - Path path = UniquePathUtilities.getPathGlobal(Options.BenchmarkCountersFile, GraalDebugConfig.Options.DumpPath, "csv"); + Path path = UniquePathUtilities.getPathGlobal(options, Options.BenchmarkCountersFile, GraalDebugConfig.Options.DumpPath, "csv"); TTY.println("Writing benchmark counters to '%s'", path); return new PrintStream(path.toFile()); } catch (FileNotFoundException e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java new file mode 100644 index 00000000000..7ffe6632298 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java @@ -0,0 +1,64 @@ +/* + * 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.meta; + +import java.util.ListIterator; + +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +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.common.ExpandLogicPhase; +import org.graalvm.compiler.phases.common.FixReadsPhase; +import org.graalvm.compiler.phases.tiers.LowTierContext; +import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.phases.tiers.SuitesCreator; + +/** + * Subclass to factor out management of address lowering. + */ +public class AddressLoweringHotSpotSuitesProvider extends HotSpotSuitesProvider { + + private final AddressLoweringPhase.AddressLowering addressLowering; + + public AddressLoweringHotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, + AddressLoweringPhase.AddressLowering addressLowering) { + super(defaultSuitesCreator, config, runtime); + this.addressLowering = addressLowering; + } + + @Override + public Suites createSuites(OptionValues options) { + Suites suites = super.createSuites(options); + + ListIterator> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class); + if (findPhase == null) { + findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class); + } + findPhase.add(new AddressLoweringPhase(addressLowering)); + + return suites; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 47ed91d18b3..590e7b1749d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -22,26 +22,27 @@ */ package org.graalvm.compiler.hotspot.meta; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace; -import static org.graalvm.compiler.core.common.LocationIdentity.any; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION; 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.compiler.hotspot.replacements.NewObjectSnippets.INIT_LOCATION; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.word.LocationIdentity.any; import java.lang.ref.Reference; import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.ObjectStamp; @@ -53,12 +54,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.CompressionNode.CompressionOp; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; +import org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; @@ -66,13 +62,18 @@ import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; +import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; +import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; import org.graalvm.compiler.hotspot.replacements.AssertionSnippets; import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; import org.graalvm.compiler.hotspot.replacements.HashCodeSnippets; @@ -96,13 +97,13 @@ import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractDeoptimizeNode; +import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoweredCallTargetNode; import org.graalvm.compiler.nodes.ParameterNode; -import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -119,13 +120,14 @@ import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardedUnsafeLoadNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.extended.OSRLocalNode; +import org.graalvm.compiler.nodes.extended.OSRLockNode; +import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode; import org.graalvm.compiler.nodes.extended.OSRStartNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.StoreHubNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode; import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode; @@ -134,6 +136,7 @@ import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorExitNode; +import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.NewMultiArrayNode; @@ -148,8 +151,10 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +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.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; @@ -194,25 +199,29 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - super.initialize(providers, providers.getSnippetReflection()); + public void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config) { + super.initialize(options, runtime, providers, providers.getSnippetReflection()); assert target == providers.getCodeCache().getTarget(); - instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); - newObjectSnippets = new NewObjectSnippets.Templates(providers, target, config); - monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); - exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); - unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); - assertionSnippets = new AssertionSnippets.Templates(providers, target); - arraycopySnippets = new ArrayCopySnippets.Templates(providers, target); - stringToBytesSnippets = new StringToBytesSnippets.Templates(providers, target); - hashCodeSnippets = new HashCodeSnippets.Templates(providers, target); - if (GeneratePIC.getValue()) { - resolveConstantSnippets = new ResolveConstantSnippets.Templates(providers, target); - profileSnippets = new ProfileSnippets.Templates(providers, target); + instanceofSnippets = new InstanceOfSnippets.Templates(options, runtime, providers, target); + newObjectSnippets = new NewObjectSnippets.Templates(options, runtime, providers, target, config); + monitorSnippets = new MonitorSnippets.Templates(options, runtime, providers, target, config.useFastLocking); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, runtime, providers, target, config.useCompressedOops ? config.getOopEncoding() : null); + exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, providers, target); + unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, providers, target); + assertionSnippets = new AssertionSnippets.Templates(options, providers, target); + arraycopySnippets = new ArrayCopySnippets.Templates(options, runtime, providers, target); + stringToBytesSnippets = new StringToBytesSnippets.Templates(options, providers, target); + hashCodeSnippets = new HashCodeSnippets.Templates(options, providers, target); + if (GeneratePIC.getValue(options)) { + resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, providers, target); + profileSnippets = new ProfileSnippets.Templates(options, providers, target); } - providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); + providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(options, providers, target)); + } + + public MonitorSnippets.Templates getMonitorSnippets() { + return monitorSnippets; } @Override @@ -303,7 +312,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } } else if (n instanceof MonitorExitNode) { if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - monitorSnippets.lower((MonitorExitNode) n, tool); + monitorSnippets.lower((MonitorExitNode) n, registers, tool); } } else if (n instanceof ArrayCopyNode) { arraycopySnippets.lower((ArrayCopyNode) n, tool); @@ -355,11 +364,17 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } else if (n instanceof IdentityHashCodeNode) { hashCodeSnippets.lower((IdentityHashCodeNode) n, tool); } else if (n instanceof ResolveConstantNode) { - resolveConstantSnippets.lower((ResolveConstantNode) n, tool); + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((ResolveConstantNode) n, tool); + } } else if (n instanceof ResolveMethodAndLoadCountersNode) { - resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); + } } else if (n instanceof InitializeKlassNode) { - resolveConstantSnippets.lower((InitializeKlassNode) n, tool); + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((InitializeKlassNode) n, tool); + } } else if (n instanceof ProfileNode) { profileSnippets.lower((ProfileNode) n, tool); } else { @@ -395,7 +410,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getHub().isConstant(); AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().klassLayoutHelperOffset); - n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE))); + n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), null, BarrierType.NONE))); } private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) { @@ -403,10 +418,17 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider return; } + ValueNode hub = n.getHub(); + GraalHotSpotVMConfig vmConfig = runtime.getVMConfig(); StructuredGraph graph = n.graph(); - assert !n.getHub().isConstant(); - AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().classMirrorOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); + assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions()); + AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset); + FloatingReadNode read = graph.unique(new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(), + null, BarrierType.NONE)); + if (vmConfig.classMirrorIsHandle) { + AddressNode address = createOffsetAddress(graph, read, 0); + read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(), null, BarrierType.NONE)); + } n.replaceAtUsagesAndDelete(read); } @@ -418,7 +440,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getValue().isConstant(); AddressNode address = createOffsetAddress(graph, n.getValue(), runtime.getVMConfig().klassOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); + FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), null, BarrierType.NONE)); n.replaceAtUsagesAndDelete(read); } @@ -428,15 +450,15 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider NodeInputList parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { - GuardingNode receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); - PiNode nonNullReceiver = graph.unique(new PiNode(receiver, ((ObjectStamp) receiver.stamp()).join(StampFactory.objectNonNull()), (ValueNode) receiverNullCheck)); + ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool); parameters.set(0, nonNullReceiver); receiver = nonNullReceiver; } JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); LoweredCallTargetNode loweredCallTarget = null; - if (InlineVTableStubs.getValue() && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { + OptionValues options = graph.getOptions(); + if (InlineVTableStubs.getValue(options) && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue(options) || invoke.isPolymorphic())) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); ResolvedJavaType receiverType = invoke.getReceiverType(); if (hsMethod.isInVirtualMethodTable(receiverType)) { @@ -473,7 +495,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider @Override protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) { if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { - return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getVMConfig().getOopEncoding()); + return HotSpotNarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getVMConfig().getOopEncoding()); } return super.loadStamp(stamp, kind, compressible); } @@ -481,7 +503,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider @Override protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, boolean compressible) { if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { - return new CompressionNode(CompressionOp.Uncompress, value, runtime.getVMConfig().getOopEncoding()); + return new HotSpotCompressionNode(CompressionOp.Uncompress, value, runtime.getVMConfig().getOopEncoding()); } return super.implicitLoadConvert(kind, value, compressible); } @@ -496,7 +518,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider @Override protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) { if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { - return new CompressionNode(CompressionOp.Compress, value, runtime.getVMConfig().getOopEncoding()); + return new HotSpotCompressionNode(CompressionOp.Compress, value, runtime.getVMConfig().getOopEncoding()); } return super.implicitStoreConvert(kind, value, compressible); } @@ -512,7 +534,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } @Override - protected void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { + protected void lowerUnsafeLoadNode(RawLoadNode load, LoweringTool tool) { StructuredGraph graph = load.graph(); if (!(load instanceof GuardedUnsafeLoadNode) && !graph.getGuardsStage().allowsFloatingGuards() && addReadBarrier(load)) { unsafeLoadSnippets.lower(load, tool); @@ -559,23 +581,64 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider ParameterNode buffer = graph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(StampFactory.forKind(runtime.getTarget().wordJavaKind)))); ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); migrationEnd.setStateAfter(osrStart.stateAfter()); - newStart.setNext(migrationEnd); FixedNode next = osrStart.next(); osrStart.setNext(null); migrationEnd.setNext(next); graph.setStart(newStart); - // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) - int localsOffset = (graph.method().getMaxLocals() - 1) * 8; + final int wordSize = target.wordSize; + + // @formatter:off + // taken from c2 locals_addr = osr_buf + (max_locals-1)*wordSize) + // @formatter:on + int localsOffset = (graph.method().getMaxLocals() - 1) * wordSize; for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.TYPE)) { int size = osrLocal.getStackKind().getSlotCount(); - int offset = localsOffset - (osrLocal.index() + size - 1) * 8; + int offset = localsOffset - (osrLocal.index() + size - 1) * wordSize; AddressNode address = createOffsetAddress(graph, buffer, offset); ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(), BarrierType.NONE)); osrLocal.replaceAndDelete(load); graph.addBeforeFixed(migrationEnd, load); } + + // @formatter:off + // taken from c2 monitors_addr = osr_buf + (max_locals+mcnt*2-1)*wordSize); + // @formatter:on + final int lockCount = osrStart.stateAfter().locksSize(); + final int locksOffset = (graph.method().getMaxLocals() + lockCount * 2 - 1) * wordSize; + + // first initialize the lock slots for all enters with the displaced marks read from the + // buffer + for (OSRMonitorEnterNode osrMonitorEnter : graph.getNodes(OSRMonitorEnterNode.TYPE)) { + MonitorIdNode monitorID = osrMonitorEnter.getMonitorId(); + OSRLockNode lock = (OSRLockNode) osrMonitorEnter.object(); + final int index = lock.index(); + + final int offsetDisplacedHeader = locksOffset - ((index * 2) + 1) * wordSize; + final int offsetLockObject = locksOffset - index * 2 * wordSize; + + // load the displaced mark from the osr buffer + AddressNode addressDisplacedHeader = createOffsetAddress(graph, buffer, offsetDisplacedHeader); + ReadNode loadDisplacedHeader = graph.add(new ReadNode(addressDisplacedHeader, any(), lock.stamp(), BarrierType.NONE)); + graph.addBeforeFixed(migrationEnd, loadDisplacedHeader); + + // we need to initialize the stack slot for the lock + BeginLockScopeNode beginLockScope = graph.add(new BeginLockScopeNode(lock.getStackKind(), monitorID.getLockDepth())); + graph.addBeforeFixed(migrationEnd, beginLockScope); + + // write the displaced mark to the correct stack slot + AddressNode addressDisplacedMark = createOffsetAddress(graph, beginLockScope, runtime.getVMConfig().basicLockDisplacedHeaderOffset); + WriteNode writeStackSlot = graph.add(new WriteNode(addressDisplacedMark, DISPLACED_MARK_WORD_LOCATION, loadDisplacedHeader, BarrierType.NONE)); + graph.addBeforeFixed(migrationEnd, writeStackSlot); + + // load the lock object from the osr buffer + AddressNode addressLockObject = createOffsetAddress(graph, buffer, offsetLockObject); + ReadNode loadObject = graph.add(new ReadNode(addressLockObject, any(), lock.stamp(), BarrierType.NONE)); + lock.replaceAndDelete(loadObject); + graph.addBeforeFixed(migrationEnd, loadObject); + } + osrStart.replaceAtUsagesAndDelete(newStart); } } @@ -616,7 +679,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } private void lowerBytecodeExceptionNode(BytecodeExceptionNode node) { - if (OmitHotExceptionStacktrace.getValue()) { + if (OmitHotExceptionStacktrace.getValue(node.getOptions())) { if (throwCachedException(node)) { return; } @@ -640,7 +703,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider graph.replaceFixedWithFixed(node, foreignCallNode); } - private boolean addReadBarrier(UnsafeLoadNode load) { + private boolean addReadBarrier(RawLoadNode load) { if (runtime.getVMConfig().useG1GC && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getStackKind() == JavaKind.Object && load.accessKind() == JavaKind.Object && !StampTool.isPointerAlwaysNull(load.object())) { ResolvedJavaType type = StampTool.typeOrNull(load.object()); @@ -659,7 +722,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider assert vtableEntryOffset > 0; // We use LocationNode.ANY_LOCATION for the reads that access the vtable // entry as HotSpot does not guarantee that this is a final value. - Stamp methodStamp = MethodPointerStamp.method(); + Stamp methodStamp = MethodPointerStamp.methodNonNull(); AddressNode address = createOffsetAddress(graph, hub, vtableEntryOffset); ReadNode metaspaceMethod = graph.add(new ReadNode(address, any(), methodStamp, BarrierType.NONE)); return metaspaceMethod; @@ -681,7 +744,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider LocationIdentity hubLocation = runtime.getVMConfig().useCompressedClassPointers ? COMPRESSED_HUB_LOCATION : HUB_LOCATION; FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, hubLocation, null, hubStamp, null, BarrierType.NONE)); if (runtime.getVMConfig().useCompressedClassPointers) { - return CompressionNode.uncompress(memoryRead, runtime.getVMConfig().getKlassEncoding()); + return HotSpotCompressionNode.uncompress(memoryRead, runtime.getVMConfig().getKlassEncoding()); } else { return memoryRead; } @@ -692,7 +755,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider ValueNode writeValue = value; if (runtime.getVMConfig().useCompressedClassPointers) { - writeValue = CompressionNode.compress(value, runtime.getVMConfig().getKlassEncoding()); + writeValue = HotSpotCompressionNode.compress(value, runtime.getVMConfig().getKlassEncoding()); } AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset); @@ -734,9 +797,4 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider public int arrayLengthOffset() { return runtime.getVMConfig().arrayOopDescLengthOffset(); } - - @Override - public LocationIdentity initLocationIdentity() { - return INIT_LOCATION; - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java index ec7de3fad23..2b7ccf97ab4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java @@ -25,8 +25,9 @@ package org.graalvm.compiler.hotspot.meta; import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -34,17 +35,17 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotAOTProfilingPlugin extends HotSpotProfilingPlugin { public static class Options { @Option(help = "Do profiling and callbacks to tiered runtime", type = OptionType.User)// - public static final OptionValue TieredAOT = new OptionValue<>(false); + public static final OptionKey TieredAOT = new OptionKey<>(false); @Option(help = "Invocation notification frequency", type = OptionType.Expert)// - public static final OptionValue TierAInvokeNotifyFreqLog = new OptionValue<>(13); + public static final OptionKey TierAInvokeNotifyFreqLog = new OptionKey<>(13); @Option(help = "Inlinee invocation notification frequency (-1 means count, but do not notify)", type = OptionType.Expert)// - public static final OptionValue TierAInvokeInlineeNotifyFreqLog = new OptionValue<>(-1); + public static final OptionKey TierAInvokeInlineeNotifyFreqLog = new OptionKey<>(-1); @Option(help = "Invocation profile probability", type = OptionType.Expert)// - public static final OptionValue TierAInvokeProfileProbabilityLog = new OptionValue<>(8); + public static final OptionKey TierAInvokeProfileProbabilityLog = new OptionKey<>(8); @Option(help = "Backedge notification frequency", type = OptionType.Expert)// - public static final OptionValue TierABackedgeNotifyFreqLog = new OptionValue<>(16); + public static final OptionKey TierABackedgeNotifyFreqLog = new OptionKey<>(16); @Option(help = "Backedge profile probability", type = OptionType.Expert)// - public static final OptionValue TierABackedgeProfileProbabilityLog = new OptionValue<>(12); + public static final OptionKey TierABackedgeProfileProbabilityLog = new OptionKey<>(12); } @Override @@ -53,27 +54,27 @@ public class HotSpotAOTProfilingPlugin extends HotSpotProfilingPlugin { } @Override - public int invokeNotifyFreqLog() { - return Options.TierAInvokeNotifyFreqLog.getValue(); + public int invokeNotifyFreqLog(OptionValues options) { + return Options.TierAInvokeNotifyFreqLog.getValue(options); } @Override - public int invokeInlineeNotifyFreqLog() { - return Options.TierAInvokeInlineeNotifyFreqLog.getValue(); + public int invokeInlineeNotifyFreqLog(OptionValues options) { + return Options.TierAInvokeInlineeNotifyFreqLog.getValue(options); } @Override - public int invokeProfilePobabilityLog() { - return Options.TierAInvokeProfileProbabilityLog.getValue(); + public int invokeProfilePobabilityLog(OptionValues options) { + return Options.TierAInvokeProfileProbabilityLog.getValue(options); } @Override - public int backedgeNotifyFreqLog() { - return Options.TierABackedgeNotifyFreqLog.getValue(); + public int backedgeNotifyFreqLog(OptionValues options) { + return Options.TierABackedgeNotifyFreqLog.getValue(options); } @Override - public int backedgeProfilePobabilityLog() { - return Options.TierABackedgeProfileProbabilityLog.getValue(); + public int backedgeProfilePobabilityLog(OptionValues options) { + return Options.TierABackedgeProfileProbabilityLog.getValue(options); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java index f7f99c64208..588982ebfb5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.meta; import org.graalvm.compiler.core.common.spi.JavaConstantFieldProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; import jdk.vm.ci.meta.MetaAccessProvider; @@ -47,7 +48,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { if (!config.foldStableValues) { return false; } - if (field.isStatic() && !isStaticFieldConstant(field)) { + if (field.isStatic() && !isStaticFieldConstant(field, tool.getOptions())) { return false; } @@ -59,7 +60,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { @Override protected boolean isFinalField(ResolvedJavaField field, ConstantFieldTool tool) { - if (field.isStatic() && !isStaticFieldConstant(field)) { + if (field.isStatic() && !isStaticFieldConstant(field, tool.getOptions())) { return false; } @@ -68,7 +69,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { private static final String SystemClassName = "Ljava/lang/System;"; - protected boolean isStaticFieldConstant(ResolvedJavaField field) { + protected boolean isStaticFieldConstant(ResolvedJavaField field, @SuppressWarnings("unused") OptionValues options) { ResolvedJavaType declaringClass = field.getDeclaringClass(); return declaringClass.isInitialized() && !declaringClass.getName().equals(SystemClassName); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java index 76b663c6b8b..e3a51de05c5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java @@ -22,7 +22,10 @@ */ package org.graalvm.compiler.hotspot.meta; +import java.util.List; + import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.hotspot.stubs.Stub; import jdk.vm.ci.meta.Value; @@ -35,4 +38,9 @@ public interface HotSpotForeignCallsProvider extends ForeignCallsProvider { * Gets the registers that must be saved across a foreign call into the runtime. */ Value[] getNativeABICallerSaveRegisters(); + + /** + * Gets the set of stubs linked to by the foreign calls represented by this object. + */ + List getStubs(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index f2ddb967437..b6330a81f72 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect; @@ -40,8 +39,11 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.stubs.ForeignCallStub; import org.graalvm.compiler.hotspot.stubs.Stub; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicMap; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CodeCacheProvider; @@ -64,7 +66,7 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC protected final HotSpotJVMCIRuntimeProvider jvmciRuntime; protected final HotSpotGraalRuntimeProvider runtime; - protected final Map foreignCalls = new HashMap<>(); + protected final EconomicMap foreignCalls = EconomicMap.create(); protected final MetaAccessProvider metaAccess; protected final CodeCacheProvider codeCache; protected final WordTypes wordTypes; @@ -144,9 +146,9 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC * cannot be re-executed. * @param killedLocations the memory locations killed by the foreign call */ - public void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, - LocationIdentity... killedLocations) { - ForeignCallStub stub = new ForeignCallStub(jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); + public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, + boolean reexecutable, LocationIdentity... killedLocations) { + ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); HotSpotForeignCallLinkage linkage = stub.getLinkage(); HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); linkage.setCompiledStub(stub); @@ -198,4 +200,17 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC public LIRKind getValueKind(JavaKind javaKind) { return LIRKind.fromJavaKind(codeCache.getTarget().arch, javaKind); } + + @Override + public List getStubs() { + List stubs = new ArrayList<>(); + for (HotSpotForeignCallLinkage linkage : foreignCalls.getValues()) { + if (linkage.isCompiledStub()) { + Stub stub = linkage.getStub(); + assert stub != null; + stubs.add(stub); + } + } + return stubs; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java index 659a79ee6d3..f9709bce633 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java @@ -23,8 +23,6 @@ package org.graalvm.compiler.hotspot.meta; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.ImmutableCodeLazy.isCalledForSnippets; -import static org.graalvm.compiler.hotspot.stubs.SnippetStub.SnippetGraphUnderConstruction; import java.util.ArrayList; import java.util.List; @@ -32,18 +30,13 @@ import java.util.List; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.options.StableOptionValue; -import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter; -import org.graalvm.compiler.replacements.SnippetTemplate; -import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.runtime.JVMCI; /** * Extends {@link HotSpotConstantFieldProvider} to override the implementation of @@ -57,25 +50,55 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi } @Override - public T readConstantField(ResolvedJavaField field, ConstantFieldTool tool) { - assert !ImmutableCode.getValue() || isCalledForSnippets(metaAccess) || SnippetGraphUnderConstruction.get() != null || - FieldReadEnabledInImmutableCode.get() == Boolean.TRUE : tool.getReceiver(); - if (!field.isStatic() && field.getName().equals("value")) { - if (getStableOptionValueType().isInstance(tool.getReceiver())) { - JavaConstant ret = tool.readValue(); - return tool.foldConstant(ret); - } - } - - return super.readConstantField(field, tool); + protected boolean isStaticFieldConstant(ResolvedJavaField field, OptionValues options) { + return super.isStaticFieldConstant(field, options) && (!ImmutableCode.getValue(options) || isEmbeddableField(field)); } /** - * In AOT mode, some fields should never be embedded even for snippets/replacements. + * The set of fields whose values cannot be constant folded in ImmutableCode mode. This is + * volatile to support double-checked locking lazy initialization. */ - @Override - protected boolean isStaticFieldConstant(ResolvedJavaField field) { - return super.isStaticFieldConstant(field) && (!ImmutableCode.getValue() || ImmutableCodeLazy.isEmbeddable(field)); + private volatile List nonEmbeddableFields; + + protected boolean isEmbeddableField(ResolvedJavaField field) { + if (nonEmbeddableFields == null) { + synchronized (this) { + if (nonEmbeddableFields == null) { + List fields = new ArrayList<>(); + try { + fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE"))); + fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE"))); + + Class characterCacheClass = Character.class.getDeclaredClasses()[0]; + assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache"))); + + Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; + assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache"))); + + Class shortCacheClass = Short.class.getDeclaredClasses()[0]; + assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache"))); + + Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; + assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache"))); + + Class longCacheClass = Long.class.getDeclaredClasses()[0]; + assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache"))); + + fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK"))); + fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"))); + } catch (SecurityException | NoSuchFieldException e) { + throw new GraalError(e); + } + nonEmbeddableFields = fields; + } + } + } + return !nonEmbeddableFields.contains(field); } @Override @@ -112,18 +135,10 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi private final MetaAccessProvider metaAccess; - private ResolvedJavaType cachedStableOptionValueType; private ResolvedJavaType cachedHotSpotVMConfigType; private ResolvedJavaType cachedSnippetCounterType; private ResolvedJavaType cachedNodeClassType; - private ResolvedJavaType getStableOptionValueType() { - if (cachedStableOptionValueType == null) { - cachedStableOptionValueType = metaAccess.lookupJavaType(StableOptionValue.class); - } - return cachedStableOptionValueType; - } - private ResolvedJavaType getHotSpotVMConfigType() { if (cachedHotSpotVMConfigType == null) { cachedHotSpotVMConfigType = metaAccess.lookupJavaType(GraalHotSpotVMConfig.class); @@ -144,102 +159,4 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi } return cachedNodeClassType; } - - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean enabled = false; - assert enabled = true; - return enabled; - } - - public static final ThreadLocal FieldReadEnabledInImmutableCode = assertionsEnabled() ? new ThreadLocal<>() : null; - - /** - * Compares two {@link StackTraceElement}s for equality, ignoring differences in - * {@linkplain StackTraceElement#getLineNumber() line number}. - */ - private static boolean equalsIgnoringLine(StackTraceElement left, StackTraceElement right) { - return left.getClassName().equals(right.getClassName()) && left.getMethodName().equals(right.getMethodName()) && left.getFileName().equals(right.getFileName()); - } - - /** - * Separate out the static initialization of {@linkplain #isEmbeddable(ResolvedJavaField) - * embeddable fields} to eliminate cycles between clinit and other locks that could lead to - * deadlock. Static code that doesn't call back into type or field machinery is probably ok but - * anything else should be made lazy. - */ - static class ImmutableCodeLazy { - - /** - * If the compiler is configured for AOT mode, {@link #readConstantField} should be only - * called for snippets or replacements. - */ - static boolean isCalledForSnippets(MetaAccessProvider metaAccess) { - assert ImmutableCode.getValue(); - ResolvedJavaMethod makeGraphMethod = null; - ResolvedJavaMethod initMethod = null; - try { - Class rjm = ResolvedJavaMethod.class; - makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, Object[].class, rjm)); - initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class)); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalError(e); - } - StackTraceElement makeGraphSTE = makeGraphMethod.asStackTraceElement(0); - StackTraceElement initSTE = initMethod.asStackTraceElement(0); - - StackTraceElement[] stackTrace = new Exception().getStackTrace(); - for (StackTraceElement element : stackTrace) { - // Ignoring line numbers should not weaken this check too much while at - // the same time making it more robust against source code changes - if (equalsIgnoringLine(makeGraphSTE, element) || equalsIgnoringLine(initSTE, element)) { - return true; - } - } - return false; - } - - /** - * Determine if it's ok to embed the value of {@code field}. - */ - static boolean isEmbeddable(ResolvedJavaField field) { - assert ImmutableCode.getValue(); - return !embeddableFields.contains(field); - } - - private static final List embeddableFields = new ArrayList<>(); - static { - try { - MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); - embeddableFields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE"))); - embeddableFields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE"))); - - Class characterCacheClass = Character.class.getDeclaredClasses()[0]; - assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache"))); - - Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; - assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache"))); - - Class shortCacheClass = Short.class.getDeclaredClasses()[0]; - assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache"))); - - Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; - assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache"))); - - Class longCacheClass = Long.class.getDeclaredClasses()[0]; - assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache"))); - - embeddableFields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK"))); - embeddableFields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"))); - } catch (SecurityException | NoSuchFieldException e) { - throw new GraalError(e); - } - } - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 3f50151d1a0..0ff708c63d7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; +import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 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 jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; -import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MutableCallSite; @@ -41,7 +40,6 @@ import java.util.zip.CRC32; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.FingerprintUtil; @@ -53,8 +51,8 @@ import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions; import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode; import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; -import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions; +import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode; import org.graalvm.compiler.hotspot.replacements.ObjectSubstitutions; import org.graalvm.compiler.hotspot.replacements.ReflectionGetCallerClassNode; @@ -90,16 +88,18 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.InlineDuringParsingPlugin; -import org.graalvm.compiler.replacements.InlineGraalDirectivesPlugin; import org.graalvm.compiler.replacements.MethodHandlePlugin; import org.graalvm.compiler.replacements.NodeIntrinsificationProvider; import org.graalvm.compiler.replacements.ReplacementsImpl; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; -import org.graalvm.compiler.replacements.WordOperationPlugin; 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.vm.ci.code.CodeUtil; import jdk.vm.ci.hotspot.HotSpotObjectConstant; @@ -126,9 +126,10 @@ public class HotSpotGraphBuilderPlugins { * @param foreignCalls * @param stampProvider */ - public static Plugins create(GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, - SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements) { - InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config); + public static Plugins create(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, + ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, + ReplacementsImpl replacements) { + InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, compilerConfiguration); Plugins plugins = new Plugins(invocationPlugins); NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes); @@ -137,7 +138,8 @@ public class HotSpotGraphBuilderPlugins { plugins.appendTypePlugin(nodePlugin); plugins.appendNodePlugin(nodePlugin); - if (GeneratePIC.getValue()) { + OptionValues options = replacements.getOptions(); + if (GeneratePIC.getValue(options)) { // AOT needs to filter out bad invokes plugins.prependNodePlugin(new NodePlugin() { @Override @@ -174,14 +176,13 @@ public class HotSpotGraphBuilderPlugins { } plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true)); plugins.appendInlineInvokePlugin(replacements); - if (InlineDuringParsing.getValue()) { + if (InlineDuringParsing.getValue(options)) { plugins.appendInlineInvokePlugin(new InlineDuringParsingPlugin()); } - plugins.appendInlineInvokePlugin(new InlineGraalDirectivesPlugin()); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(options)) { plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); - if (TieredAOT.getValue()) { + if (TieredAOT.getValue(options)) { plugins.setProfilingPlugin(new HotSpotAOTProfilingPlugin()); } } @@ -190,15 +191,14 @@ public class HotSpotGraphBuilderPlugins { @Override public void run() { - BytecodeProvider replacementBytecodeProvider = replacements.getReplacementBytecodeProvider(); - registerObjectPlugins(invocationPlugins, replacementBytecodeProvider); + BytecodeProvider replacementBytecodeProvider = replacements.getDefaultReplacementBytecodeProvider(); + registerObjectPlugins(invocationPlugins, options, replacementBytecodeProvider); registerClassPlugins(plugins, config, replacementBytecodeProvider); registerSystemPlugins(invocationPlugins, foreignCalls); registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacementBytecodeProvider); registerCallSitePlugins(invocationPlugins); registerReflectionPlugins(invocationPlugins, replacementBytecodeProvider); registerConstantPoolPlugins(invocationPlugins, wordTypes, config, replacementBytecodeProvider); - registerStableOptionPlugins(invocationPlugins, snippetReflection); registerAESPlugins(invocationPlugins, config, replacementBytecodeProvider); registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider); registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider); @@ -213,9 +213,9 @@ public class HotSpotGraphBuilderPlugins { return plugins; } - private static void registerObjectPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { + private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, BytecodeProvider bytecodeProvider) { Registration r = new Registration(plugins, Object.class, bytecodeProvider); - if (!GeneratePIC.getValue()) { + if (!GeneratePIC.getValue(options)) { // FIXME: clone() requires speculation and requires a fix in here (to check that // b.getAssumptions() != null), and in ReplacementImpl.getSubstitution() where there is // an instantiation of IntrinsicGraphBuilder using a constructor that sets @@ -256,7 +256,7 @@ public class HotSpotGraphBuilderPlugins { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { ValueNode javaClass = receiver.get(); - LogicNode condition = b.recursiveAppend(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), javaClass, object, true)); + LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), javaClass, object, true)); if (condition.isTautology()) { b.addPush(JavaKind.Object, object); } else { @@ -327,7 +327,8 @@ public class HotSpotGraphBuilderPlugins { */ private static ValueNode getMetaspaceConstantPool(GraphBuilderContext b, ValueNode constantPoolOop, WordTypes wordTypes, GraalHotSpotVMConfig config) { // ConstantPool.constantPoolOop is in fact the holder class. - ClassGetHubNode klass = b.add(new ClassGetHubNode(constantPoolOop)); + ValueNode value = b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None); + ValueNode klass = b.add(ClassGetHubNode.create(value, b.getMetaAccess(), b.getConstantReflection(), false)); boolean notCompressible = false; AddressNode constantsAddress = b.add(new OffsetAddressNode(klass, b.add(ConstantNode.forLong(config.instanceKlassConstantsOffset)))); @@ -442,21 +443,6 @@ public class HotSpotGraphBuilderPlugins { r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class); } - private static void registerStableOptionPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection) { - Registration r = new Registration(plugins, StableOptionValue.class); - r.register1("getValue", Receiver.class, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - if (receiver.isConstant()) { - StableOptionValue option = snippetReflection.asObject(StableOptionValue.class, (JavaConstant) receiver.get().asConstant()); - b.addPush(JavaKind.Object, ConstantNode.forConstant(snippetReflection.forObject(option.getValue()), b.getMetaAccess())); - return true; - } - return false; - } - }); - } - public static final String cbcEncryptName; public static final String cbcDecryptName; public static final String aesEncryptName; @@ -466,7 +452,7 @@ public class HotSpotGraphBuilderPlugins { public static final String constantPoolClass; static { - if (Java8OrEarlier) { + if (JDK9Method.Java8OrEarlier) { cbcEncryptName = "encrypt"; cbcDecryptName = "decrypt"; aesEncryptName = "encryptBlock"; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 726087805f3..ff2fb37b411 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -22,15 +22,11 @@ */ package org.graalvm.compiler.hotspot.meta; +import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.BACKEDGE_EVENT; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY; @@ -38,8 +34,9 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_ import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; import static org.graalvm.compiler.hotspot.HotSpotBackend.IC_MISS_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_MULTIPLY; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_SQUARE; import static org.graalvm.compiler.hotspot.HotSpotBackend.MULTIPLY_TO_LEN; @@ -47,16 +44,16 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.MUL_ADD; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SQUARE_TO_LEN; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNPACK_FRAMES; import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR; import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; @@ -77,7 +74,6 @@ import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITORE import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITOREXIT; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_ARRAY; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_INSTANCE; -import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.INIT_LOCATION; import static org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions.THREAD_IS_INTERRUPTED; import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPOSTCALL; import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPRECALL; @@ -99,20 +95,16 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.Una 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 jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.stubs.ArrayStoreExceptionStub; import org.graalvm.compiler.hotspot.stubs.ClassCastExceptionStub; import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub; @@ -125,8 +117,11 @@ import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; import org.graalvm.compiler.hotspot.stubs.VerifyOopStub; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicMap; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -183,7 +178,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall } } - private void registerArraycopyDescriptor(Map descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) { + private void registerArraycopyDescriptor(EconomicMap descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) { ForeignCallDescriptor desc = descMap.get(routine); if (desc == null) { desc = buildDescriptor(kind, aligned, disjoint, uninit, killAny, routine); @@ -231,7 +226,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall * but only within the same Kind. For instance short and char are the same copy routines but * they kill different memory so they still have to be distinct. */ - Map descMap = new HashMap<>(); + EconomicMap descMap = EconomicMap.create(); registerArraycopyDescriptor(descMap, kind, false, false, uninit, false, routine); registerArraycopyDescriptor(descMap, kind, true, false, uninit, false, alignedRoutine); registerArraycopyDescriptor(descMap, kind, false, true, uninit, false, disjointRoutine); @@ -245,12 +240,10 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall } } - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig c = runtime.getVMConfig(); - if (!PreferGraalStubs.getValue()) { - registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - } + registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); @@ -269,17 +262,8 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); - registerForeignCall(FETCH_UNROLL_INFO, c.deoptimizationFetchUnrollInfo, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); - registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, NOT_REEXECUTABLE, any()); - - /* - * We cannot use LEAF_SP here because on some architectures we have to align the stack - * manually before calling into the VM. See {@link - * AMD64HotSpotEnterUnpackFramesStackFrameOp#emitCode}. - */ - registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, any()); CreateExceptionStub.registerForeignCalls(c, this); @@ -290,47 +274,47 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - link(new NewInstanceStub(providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, SAFEPOINT, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); - link(new NewArrayStub(providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, SAFEPOINT, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); - link(new ExceptionHandlerStub(providers, foreignCalls.get(EXCEPTION_HANDLER))); - link(new UnwindExceptionToCallerStub(providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any()))); - link(new VerifyOopStub(providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); - link(new ArrayStoreExceptionStub(providers, registerStubCall(CREATE_ARRAY_STORE_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new ClassCastExceptionStub(providers, registerStubCall(CREATE_CLASS_CAST_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new NullPointerExceptionStub(providers, registerStubCall(CREATE_NULL_POINTER_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new OutOfBoundsExceptionStub(providers, registerStubCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new NewInstanceStub(options, providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); + link(new NewArrayStub(options, providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); + link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER))); + link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any()))); + link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); + link(new ArrayStoreExceptionStub(options, providers, registerStubCall(CREATE_ARRAY_STORE_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new ClassCastExceptionStub(options, providers, registerStubCall(CREATE_CLASS_CAST_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new NullPointerExceptionStub(options, providers, registerStubCall(CREATE_NULL_POINTER_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION); - linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION); + linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + 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, 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); + linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(options)) { registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); CompilerRuntimeHotSpotVMConfig cr = new CompilerRuntimeHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore()); - linkForeignCall(providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - linkForeignCall(providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); - linkForeignCall(providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); - linkForeignCall(providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + linkForeignCall(options, providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); } // Cannot be a leaf as VM acquires Thread_lock which requires thread_in_vm state - linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); registerArrayCopy(JavaKind.Byte, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy); registerArrayCopy(JavaKind.Boolean, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java index 244579972dd..076d4a98700 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java @@ -22,9 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; + import java.lang.reflect.Type; +import java.util.Set; 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; @@ -35,8 +39,12 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; 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 org.graalvm.util.EconomicSet; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaType; @@ -44,10 +52,19 @@ import jdk.vm.ci.meta.ResolvedJavaType; * Extension of {@link InvocationPlugins} that disables plugins based on runtime configuration. */ final class HotSpotInvocationPlugins extends InvocationPlugins { - final GraalHotSpotVMConfig config; + private final GraalHotSpotVMConfig config; + private final EconomicSet trustedModules; + private final ClassLoader extLoader; - HotSpotInvocationPlugins(GraalHotSpotVMConfig config) { + HotSpotInvocationPlugins(GraalHotSpotVMConfig config, CompilerConfiguration compilerConfiguration) { this.config = config; + if (Java8OrEarlier) { + extLoader = getExtLoader(); + trustedModules = null; + } else { + extLoader = null; + trustedModules = initTrustedModules(compilerConfiguration); + } } @Override @@ -71,7 +88,7 @@ final class HotSpotInvocationPlugins extends InvocationPlugins { assert plugin.inlineOnly() : String.format("plugin that creates a %s (%s) must return true for inlineOnly(): %s", MacroNode.class.getSimpleName(), node, plugin); } } - if (GraalOptions.ImmutableCode.getValue()) { + if (GraalOptions.ImmutableCode.getValue(b.getOptions())) { for (Node node : newNodes) { if (node.hasUsages() && node instanceof ConstantNode) { ConstantNode c = (ConstantNode) node; @@ -95,4 +112,71 @@ final class HotSpotInvocationPlugins extends InvocationPlugins { ResolvedJavaType type = StampTool.typeOrNull(node); 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 + protected 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.invoke(javaClass); + return trustedModules.contains(module); + } + } + 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); + } + } + + private static EconomicSet initTrustedModules(CompilerConfiguration compilerConfiguration) throws GraalError { + try { + EconomicSet res = EconomicSet.create(); + Object compilerConfigurationModule = JDK9Method.getModule.invoke(compilerConfiguration.getClass()); + res.add(compilerConfigurationModule); + Class moduleClass = compilerConfigurationModule.getClass(); + Object layer = new JDK9Method(moduleClass, "getLayer").invoke(compilerConfigurationModule); + Class layerClass = layer.getClass(); + JDK9Method getName = new JDK9Method(moduleClass, "getName"); + Set modules = new JDK9Method(layerClass, "modules").invoke(layer); + Object descriptor = new JDK9Method(moduleClass, "getDescriptor").invoke(compilerConfigurationModule); + Class moduleDescriptorClass = descriptor.getClass(); + Set requires = new JDK9Method(moduleDescriptorClass, "requires").invoke(descriptor); + JDK9Method requireNameGetter = null; + for (Object require : requires) { + if (requireNameGetter == null) { + requireNameGetter = new JDK9Method(require.getClass(), "name"); + } + String name = requireNameGetter.invoke(require); + for (Object module : modules) { + String moduleName = getName.invoke(module); + if (moduleName.equals(name)) { + res.add(module); + } + } + } + return res; + } catch (Exception e) { + throw new GraalError(e); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java index 95b21a0d201..c133a5f8f4c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java @@ -24,11 +24,12 @@ package org.graalvm.compiler.hotspot.meta; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodes.spi.LoweringProvider; +import org.graalvm.compiler.options.OptionValues; /** * HotSpot implementation of {@link LoweringProvider}. */ public interface HotSpotLoweringProvider extends LoweringProvider { - void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config); + void initialize(OptionValues options, HotSpotProviders providers, GraalHotSpotVMConfig config); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java index 10b2255a3dc..c0f91779bfb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.meta; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.FieldReadEnabledInImmutableCode; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.nodes.ConstantNode; @@ -34,8 +33,8 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.TypePlugin; import org.graalvm.compiler.nodes.util.ConstantFoldUtil; -import org.graalvm.compiler.replacements.WordOperationPlugin; import org.graalvm.compiler.word.Word; +import org.graalvm.compiler.word.WordOperationPlugin; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -90,7 +89,7 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { @Override public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { - if (!ImmutableCode.getValue() || b.parsingIntrinsic()) { + if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (object.isConstant()) { JavaConstant asJavaConstant = object.asJavaConstant(); if (tryReadField(b, field, asJavaConstant)) { @@ -106,7 +105,7 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { @Override public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { - if (!ImmutableCode.getValue() || b.parsingIntrinsic()) { + if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (tryReadField(b, field, null)) { return true; } @@ -118,21 +117,11 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { } private static boolean tryReadField(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { - // FieldReadEnabledInImmutableCode is non null only if assertions are enabled - if (FieldReadEnabledInImmutableCode != null && ImmutableCode.getValue()) { - FieldReadEnabledInImmutableCode.set(Boolean.TRUE); - try { - return tryConstantFold(b, field, object); - } finally { - FieldReadEnabledInImmutableCode.set(null); - } - } else { - return tryConstantFold(b, field, object); - } + return tryConstantFold(b, field, object); } private static boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { - ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object); + ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object, b.getOptions()); if (result != null) { result = b.getGraph().unique(result); b.push(field.getJavaKind(), result); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java index d0dad67e740..311e4199e97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java @@ -33,28 +33,29 @@ import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { public static class Options { @Option(help = "Emit profiling of invokes", type = OptionType.Expert)// - public static final OptionValue ProfileInvokes = new OptionValue<>(true); + public static final OptionKey ProfileInvokes = new OptionKey<>(true); @Option(help = "Emit profiling of backedges", type = OptionType.Expert)// - public static final OptionValue ProfileBackedges = new OptionValue<>(true); + public static final OptionKey ProfileBackedges = new OptionKey<>(true); } - public abstract int invokeNotifyFreqLog(); + public abstract int invokeNotifyFreqLog(OptionValues options); - public abstract int invokeInlineeNotifyFreqLog(); + public abstract int invokeInlineeNotifyFreqLog(OptionValues options); - public abstract int invokeProfilePobabilityLog(); + public abstract int invokeProfilePobabilityLog(OptionValues options); - public abstract int backedgeNotifyFreqLog(); + public abstract int backedgeNotifyFreqLog(OptionValues options); - public abstract int backedgeProfilePobabilityLog(); + public abstract int backedgeProfilePobabilityLog(OptionValues options); @Override public boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method) { @@ -64,8 +65,9 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileInvoke(GraphBuilderContext builder, ResolvedJavaMethod method, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileInvokes.getValue() && !method.isClassInitializer()) { - ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(), invokeProfilePobabilityLog())); + OptionValues options = builder.getOptions(); + if (Options.ProfileInvokes.getValue(options) && !method.isClassInitializer()) { + ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(options), invokeProfilePobabilityLog(options))); p.setStateBefore(frameState); } } @@ -73,8 +75,9 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileGoto(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, int targetBci, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileBackedges.getValue() && targetBci <= bci) { - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(), backedgeProfilePobabilityLog(), bci, targetBci)); + OptionValues options = builder.getOptions(); + if (Options.ProfileBackedges.getValue(options) && targetBci <= bci) { + ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), bci, targetBci)); p.setStateBefore(frameState); } } @@ -82,7 +85,8 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileIf(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, LogicNode condition, int trueBranchBci, int falseBranchBci, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileBackedges.getValue() && (falseBranchBci <= bci || trueBranchBci <= bci)) { + OptionValues options = builder.getOptions(); + if (Options.ProfileBackedges.getValue(options) && (falseBranchBci <= bci || trueBranchBci <= bci)) { boolean negate = false; int targetBci = trueBranchBci; if (falseBranchBci <= bci) { @@ -95,7 +99,7 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { ValueNode trueValue = builder.append(ConstantNode.forBoolean(!negate)); ValueNode falseValue = builder.append(ConstantNode.forBoolean(negate)); ConditionalNode branchCondition = builder.append(new ConditionalNode(condition, trueValue, falseValue)); - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(), backedgeProfilePobabilityLog(), branchCondition, bci, targetBci)); + ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), branchCondition, bci, targetBci)); p.setStateBefore(frameState); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java index 2b65a88709b..6935b9b695e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java @@ -27,7 +27,6 @@ import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; 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.NodeCostProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.util.Providers; @@ -49,10 +48,10 @@ public class HotSpotProviders extends Providers { private final Plugins graphBuilderPlugins; public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField, - HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, NodeCostProvider nodeCostProvider, SuitesProvider suites, + HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, SuitesProvider suites, HotSpotRegistersProvider registers, SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins) { - super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), nodeCostProvider); + super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider()); this.suites = suites; this.registers = registers; this.snippetReflection = snippetReflection; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java index 32d7281b31a..adbb0db8795 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java @@ -22,17 +22,16 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases; import java.util.ListIterator; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; @@ -50,16 +49,14 @@ import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.AddressLoweringPhase; -import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ExpandLogicPhase; -import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.SuitesCreator; @@ -71,36 +68,34 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { protected final GraalHotSpotVMConfig config; protected final HotSpotGraalRuntimeProvider runtime; - private final AddressLowering addressLowering; private final SuitesCreator defaultSuitesCreator; - public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, AddressLowering addressLowering) { + public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime) { this.defaultSuitesCreator = defaultSuitesCreator; this.config = config; this.runtime = runtime; - this.addressLowering = addressLowering; this.defaultGraphBuilderSuite = createGraphBuilderSuite(); } @Override - public Suites createSuites() { - Suites ret = defaultSuitesCreator.createSuites(); + public Suites createSuites(OptionValues options) { + Suites ret = defaultSuitesCreator.createSuites(options); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { // lowering introduces class constants, therefore it must be after lowering - ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null)); - if (VerifyPhases.getValue()) { + ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config)); + if (VerifyPhases.getValue(options)) { ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); } - if (GeneratePIC.getValue()) { - // EliminateRedundantInitializationPhase must happen before the first lowering. + if (GeneratePIC.getValue(options)) { ListIterator> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); highTierLowering.previous(); highTierLowering.add(new EliminateRedundantInitializationPhase()); - if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue()) { - highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue())); + if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { + highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); } - ret.getMidTier().findPhase(LoopSafepointInsertionPhase.class).add(new ReplaceConstantNodesPhase()); + ListIterator> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class); + midTierLowering.add(new ReplaceConstantNodesPhase()); // Replace inlining policy ListIterator> iter = ret.getHighTier().findPhase(InliningPhase.class); @@ -111,12 +106,10 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { } ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config)); - if (VerifyPhases.getValue()) { + if (VerifyPhases.getValue(options)) { ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config)); } - ret.getLowTier().findPhase(ExpandLogicPhase.class).add(new AddressLoweringPhase(addressLowering)); - return ret; } @@ -131,7 +124,7 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { * encoding and decoding process work correctly. The decoding performs canonicalization during * decoding, so the decoded graph can be different than the encoded graph - we cannot check them * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the - * encoding itself}, i.e., performs a decoding without canoncialization and checks the graphs + * encoding itself}, i.e., performs a decoding without canonicalization and checks the graphs * for equality. */ private boolean appendGraphEncoderTest(PhaseSuite suite) { @@ -140,10 +133,10 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { protected void run(StructuredGraph graph, HighTierContext context) { EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); - SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), - context.getStampProvider(), !ImmutableCode.getValue(), runtime.getTarget().arch); - StructuredGraph targetGraph = new StructuredGraph(graph.method(), AllowAssumptions.YES, INVALID_COMPILATION_ID); - graphDecoder.decode(targetGraph, encodedGraph); + StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), AllowAssumptions.YES).method(graph.method()).build(); + SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), + context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions())); + graphDecoder.decode(encodedGraph); } @Override @@ -169,9 +162,9 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { } @Override - public LIRSuites createLIRSuites() { - LIRSuites suites = defaultSuitesCreator.createLIRSuites(); - String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(); + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites suites = defaultSuitesCreator.createLIRSuites(options); + String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); if (profileInstructions != null) { suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java index cb47a5ad446..354b8e1f8af 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.LocationIdentity.any; 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 org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BridgeMethodUtils; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; @@ -40,7 +39,6 @@ import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; import org.graalvm.compiler.hotspot.word.HotSpotOperation; import org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode; import org.graalvm.compiler.hotspot.word.PointerCastNode; -import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; @@ -52,8 +50,9 @@ import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.type.StampTool; -import org.graalvm.compiler.replacements.WordOperationPlugin; +import org.graalvm.compiler.word.WordOperationPlugin; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -110,7 +109,7 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); - b.addPush(returnKind, new ConditionalNode(comparison, eqValue, neValue)); + b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue)); break; case IS_NULL: @@ -118,8 +117,8 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { ValueNode pointer = args[0]; assert pointer.stamp() instanceof MetaspacePointerStamp; - LogicNode isNull = b.add(IsNullNode.create(pointer)); - b.addPush(returnKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); + LogicNode isNull = b.addWithInputs(IsNullNode.create(pointer)); + b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); break; case FROM_POINTER: @@ -149,11 +148,6 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant()); } ReadNode read = b.add(new ReadNode(address, location, readStamp, BarrierType.NONE)); - /* - * The read must not float outside its block otherwise it may float above an - * explicit zero check on its base address. - */ - read.setGuard(AbstractBeginNode.prevBegin(read)); b.push(returnKind, read); break; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java index d3c5b867643..63657a69d24 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.nodeinfo.InputType.Memory; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; @@ -39,7 +38,9 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; 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.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; /** @@ -59,6 +60,11 @@ public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implement this.lockDepth = lockDepth; } + public BeginLockScopeNode(JavaKind kind, int lockDepth) { + super(TYPE, StampFactory.forKind(kind)); + this.lockDepth = lockDepth; + } + @Override public boolean hasSideEffect() { return false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java index bff064cfa38..b1fbaa0a564 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.ControlFlowAnchored; @@ -40,7 +40,7 @@ import jdk.vm.ci.meta.JavaKind; * A high-level intrinsic for getting an address inside of an object. During lowering it will be * moved next to any uses to avoid creating a derived pointer that is live across a safepoint. */ -@NodeInfo(cycles = CYCLES_3, size = SIZE_2) +@NodeInfo(cycles = CYCLES_1, size = NodeSize.SIZE_1) public final class ComputeObjectAddressNode extends FixedWithNextNode implements Lowerable, ControlFlowAnchored { public static final NodeClass TYPE = NodeClass.create(ComputeObjectAddressNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java deleted file mode 100644 index 06a26f6f08b..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code {@code Deoptimization::fetch_unroll_info}. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public final class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(DeoptimizationFetchUnrollInfoCallNode.class); - @Input SaveAllRegistersNode registerSaver; - @Input ValueNode mode; - protected final ForeignCallsProvider foreignCalls; - - public DeoptimizationFetchUnrollInfoCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode mode) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(FETCH_UNROLL_INFO.getResultType()))); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - this.mode = mode; - this.foreignCalls = foreignCalls; - } - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } - - public SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - /** - * Returns the node representing the exec_mode/unpack_kind used during this fetch_unroll_info - * call. - */ - public ValueNode getMode() { - return mode; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitDeoptimizationFetchUnrollInfoCall(gen.operand(getMode()), getSaveRegistersOp()); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native Word fetchUnrollInfo(long registerSaver, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java index 09aa3e359e9..87982010819 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.DeoptimizationReason; /** * Removes the current frame and tail calls the uncommon trap routine. */ -@NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}", cycles = CYCLES_1, size = SIZE_3) +@NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}", cycles = CYCLES_8, size = SIZE_8) public final class DeoptimizeCallerNode extends ControlSinkNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(DeoptimizeCallerNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java index db08803de12..4c2f3782a91 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.asm.NumUtil.roundUp; +import static org.graalvm.compiler.core.common.NumUtil.roundUp; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java deleted file mode 100644 index 74eac1ede7e..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java +++ /dev/null @@ -1,103 +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. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.InputType.Association; -import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_30; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.StateSplit; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.java.CompareAndSwapNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -/** - * A special purpose store node that differs from {@link CompareAndSwapNode} in that it is not a - * {@link StateSplit} and it {@linkplain #compareAndSwap(Address, Word, Word, LocationIdentity)} - * returns either the expected value or the compared against value instead of a boolean. - */ -@NodeInfo(allowedUsageTypes = Memory, cycles = CYCLES_30, size = SIZE_8) -public final class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(DirectCompareAndSwapNode.class); - @Input(Association) AddressNode address; - @Input ValueNode expectedValue; - @Input ValueNode newValue; - - protected final LocationIdentity locationIdentity; - - public DirectCompareAndSwapNode(ValueNode address, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) { - super(TYPE, expected.stamp()); - this.address = (AddressNode) address; - this.expectedValue = expected; - this.newValue = newValue; - this.locationIdentity = locationIdentity; - } - - public AddressNode getAddress() { - return address; - } - - public ValueNode expectedValue() { - return expectedValue; - } - - public ValueNode newValue() { - return newValue; - } - - @Override - public LocationIdentity getLocationIdentity() { - return locationIdentity; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotNodeLIRBuilder) gen).visitDirectCompareAndSwap(this); - } - - /** - * Compares an expected value with the actual value in a location denoted by an address. Iff - * they are same, {@code newValue} is placed into the location and the {@code expectedValue} is - * returned. Otherwise, the actual value is returned. All of the above is performed in one - * atomic hardware transaction. - * - * @param address the address to be atomically tested and updated - * @param expectedValue if this value is currently in the field, perform the swap - * @param newValue the new value to put into the field - * @return either {@code expectedValue} or the actual value - */ - @NodeIntrinsic - public static native Word compareAndSwap(Address address, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java index 53db7d9d1ae..0c12d547d83 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java @@ -26,7 +26,6 @@ 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 org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -35,6 +34,7 @@ import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; 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; /** * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java deleted file mode 100644 index 2685973c15e..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_20; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_10; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * Emits code to enter a low-level stack frame specifically to call out to the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@NodeInfo(cycles = CYCLES_20, size = SIZE_10) -public final class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - public static final NodeClass TYPE = NodeClass.create(EnterUnpackFramesStackFrameNode.class); - - @Input ValueNode framePc; - @Input ValueNode senderSp; - @Input ValueNode senderFp; - @Input SaveAllRegistersNode registerSaver; - - public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.framePc = framePc; - this.senderSp = senderSp; - this.senderFp = senderFp; - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value operandValue = gen.operand(framePc); - Value senderSpValue = gen.operand(senderSp); - Value senderFpValue = gen.operand(senderFp); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue, getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp, long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java index 3254f6b082a..4759072762f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_100; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_100; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; -@NodeInfo(cycles = CYCLES_100, size = SIZE_100) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePostWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java index e290a14f778..a7b6cc8d47d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_100; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_100; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; -@NodeInfo(cycles = CYCLES_100, size = SIZE_100) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePreWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java index d4a994cc8ca..522e20f9470 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java @@ -22,15 +22,15 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; -@NodeInfo(cycles = CYCLES_50, size = SIZE_50) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public class G1PostWriteBarrier extends ObjectWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1PostWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java index 4e21beb405c..521954be2dc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; @@ -33,7 +33,7 @@ import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; -@NodeInfo(cycles = CYCLES_50, size = SIZE_50) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public final class G1PreWriteBarrier extends ObjectWriteBarrier implements DeoptimizingNode.DeoptBefore { public static final NodeClass TYPE = NodeClass.create(G1PreWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java index bc59c044f24..26c3bb75715 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -36,7 +36,7 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled. */ -@NodeInfo(cycles = CYCLES_50, size = SIZE_50) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public final class G1ReferentFieldReadBarrier extends ObjectWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ReferentFieldReadBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java index 8d0575fe6b5..3287063e209 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -72,8 +73,8 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab * @param config * @param markId id of the config value */ - public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId) { - super(TYPE, StampFactory.forNodeIntrinsic()); + public GraalHotSpotVMConfigNode(@InjectedNodeParameter Stamp stamp, @InjectedNodeParameter GraalHotSpotVMConfig config, int markId) { + super(TYPE, stamp); this.config = config; this.markId = markId; } @@ -85,7 +86,7 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab * @param markId id of the config value * @param kind explicit type of the node */ - public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId, JavaKind kind) { + public GraalHotSpotVMConfigNode(GraalHotSpotVMConfig config, int markId, JavaKind kind) { super(TYPE, StampFactory.forKind(kind)); this.config = config; this.markId = markId; @@ -100,13 +101,13 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab @NodeIntrinsic private static native boolean areConfigValuesConstant(); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native long loadLongConfigValue(@ConstantNodeParameter int markId); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native int loadIntConfigValue(@ConstantNodeParameter int markId); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native byte loadByteConfigValue(@ConstantNodeParameter int markId); public static long cardTableAddress() { @@ -170,20 +171,20 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab @Override public Node canonical(CanonicalizerTool tool) { if (markId == 0) { - return ConstantNode.forBoolean(!GeneratePIC.getValue()); + return ConstantNode.forBoolean(!GeneratePIC.getValue(tool.getOptions())); } - if (!GeneratePIC.getValue()) { - if (markId == cardTableAddressMark(config)) { + if (!GeneratePIC.getValue(tool.getOptions())) { + if (markId == config.MARKID_CARD_TABLE_ADDRESS) { return ConstantNode.forLong(config.cardtableStartAddress); - } else if (markId == heapTopAddressMark(config)) { + } else if (markId == config.MARKID_HEAP_TOP_ADDRESS) { return ConstantNode.forLong(config.heapTopAddress); - } else if (markId == heapEndAddressMark(config)) { + } else if (markId == config.MARKID_HEAP_END_ADDRESS) { return ConstantNode.forLong(config.heapEndAddress); - } else if (markId == crcTableAddressMark(config)) { + } else if (markId == config.MARKID_CRC_TABLE_ADDRESS) { return ConstantNode.forLong(config.crcTableAddress); - } else if (markId == logOfHeapRegionGrainBytesMark(config)) { + } else if (markId == config.MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES) { return ConstantNode.forInt(config.logOfHRGrainBytes); - } else if (markId == inlineContiguousAllocationSupportedMark(config)) { + } else if (markId == config.MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) { return ConstantNode.forBoolean(config.inlineContiguousAllocationSupported); } else { assert false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java new file mode 100644 index 00000000000..ecd8ba0b811 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java @@ -0,0 +1,83 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.nodes; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; + +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.CompressionNode; +import org.graalvm.compiler.nodes.ValueNode; + +import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; +import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; + +@NodeInfo(nameTemplate = "{p#op/s}", cycles = CYCLES_2, size = SIZE_2) +public final class HotSpotCompressionNode extends CompressionNode { + + public static final NodeClass TYPE = NodeClass.create(HotSpotCompressionNode.class); + + public HotSpotCompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) { + super(TYPE, op, input, HotSpotNarrowOopStamp.mkStamp(op, input.stamp(), encoding), encoding); + } + + public static HotSpotCompressionNode compress(ValueNode input, CompressEncoding encoding) { + return input.graph().unique(new HotSpotCompressionNode(CompressionOp.Compress, input, encoding)); + } + + public static CompressionNode uncompress(ValueNode input, CompressEncoding encoding) { + return input.graph().unique(new HotSpotCompressionNode(CompressionOp.Uncompress, input, encoding)); + } + + @Override + protected Constant compress(Constant c) { + if (JavaConstant.NULL_POINTER.equals(c)) { + return HotSpotCompressedNullConstant.COMPRESSED_NULL; + } else if (c instanceof HotSpotConstant) { + return ((HotSpotConstant) c).compress(); + } else { + throw GraalError.shouldNotReachHere("invalid constant input for compress op: " + c); + } + } + + @Override + protected Constant uncompress(Constant c) { + if (c instanceof HotSpotConstant) { + return ((HotSpotConstant) c).uncompress(); + } else { + throw GraalError.shouldNotReachHere("invalid constant input for uncompress op: " + c); + } + } + + @Override + protected Stamp mkStamp(Stamp input) { + return HotSpotNarrowOopStamp.mkStamp(op, input, encoding); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotNodeCostProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotNodeCostProvider.java deleted file mode 100644 index 86785dd20d8..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotNodeCostProvider.java +++ /dev/null @@ -1,71 +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.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_20; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_30; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_30; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode; -import org.graalvm.compiler.nodeinfo.NodeCycles; -import org.graalvm.compiler.nodeinfo.NodeSize; -import org.graalvm.compiler.nodes.spi.DefaultNodeCostProvider; -import org.graalvm.compiler.nodes.type.StampTool; - -import jdk.vm.ci.meta.ResolvedJavaType; - -public abstract class HotSpotNodeCostProvider extends DefaultNodeCostProvider { - - @Override - public NodeSize size(Node n) { - if (n instanceof ObjectCloneNode) { - ResolvedJavaType type = StampTool.typeOrNull(((ObjectCloneNode) n).getObject()); - if (type != null) { - if (type.isArray()) { - return SIZE_30; - } else { - return SIZE_20; - } - } - } - return super.size(n); - } - - @Override - public NodeCycles cycles(Node n) { - if (n instanceof ObjectCloneNode) { - ResolvedJavaType type = StampTool.typeOrNull(((ObjectCloneNode) n).getObject()); - if (type != null) { - if (type.isArray()) { - return CYCLES_30; - } else { - return CYCLES_20; - } - } - } - return super.cycles(n); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java index de069c21fe8..1eee507fcdf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_15; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.core.common.type.StampFactory; @@ -40,7 +40,7 @@ import org.graalvm.compiler.word.Word; * Sets up the {@linkplain HotSpotBackend#EXCEPTION_HANDLER_IN_CALLER arguments} expected by an * exception handler in the caller's frame, removes the current frame and jumps to said handler. */ -@NodeInfo(cycles = CYCLES_15, size = SIZE_8) +@NodeInfo(cycles = CYCLES_8, size = SIZE_8) public final class JumpToExceptionHandlerInCallerNode extends ControlSinkNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(JumpToExceptionHandlerInCallerNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java index f7ca42ff833..0a9a11d13dc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java deleted file mode 100644 index 45e076f64e2..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java +++ /dev/null @@ -1,64 +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.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Emits code to leave (pop) the current low-level stack frame. This operation also removes the - * return address if its location is on the stack. - */ -@NodeInfo(cycles = CYCLES_10, size = SIZE_6) -public final class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveCurrentStackFrameNode.class); - @Input SaveAllRegistersNode registerSaver; - - public LeaveCurrentStackFrameNode(ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame(getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void leaveCurrentStackFrame(long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java deleted file mode 100644 index 843dbc65947..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java +++ /dev/null @@ -1,67 +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.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node - * is only used in {@link DeoptimizationStub}. - */ -@NodeInfo(cycles = CYCLES_3, size = SIZE_2) -public final class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveDeoptimizedStackFrameNode.class); - @Input ValueNode frameSize; - @Input ValueNode initialInfo; - - public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { - super(TYPE, StampFactory.forVoid()); - this.frameSize = frameSize; - this.initialInfo = initialInfo; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value frameSizeValue = gen.operand(frameSize); - Value initialInfoValue = gen.operand(initialInfo); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveDeoptimizedStackFrame(frameSizeValue, initialInfoValue); - } - - @NodeIntrinsic - public static native void leaveDeoptimizedStackFrame(int frameSize, Word initialInfo); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java deleted file mode 100644 index 2c54a4a2c83..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java +++ /dev/null @@ -1,65 +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.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Emits code to leave a low-level stack frame specifically to call out to the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@NodeInfo(cycles = CYCLES_10, size = SIZE_6) -public final class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveUnpackFramesStackFrameNode.class); - @Input SaveAllRegistersNode registerSaver; - - public LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame(getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void leaveUnpackFramesStackFrame(long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java deleted file mode 100644 index e779da57db9..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java +++ /dev/null @@ -1,72 +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.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code implementing the uncommon trap logic. - */ -@NodeInfo(cycles = CYCLES_8, size = SIZE_6) -public final class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(PushInterpreterFrameNode.class); - @Input ValueNode framePc; - @Input ValueNode frameSize; - @Input ValueNode senderSp; - @Input ValueNode initialInfo; - - public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { - super(TYPE, StampFactory.forVoid()); - this.frameSize = frameSize; - this.framePc = framePc; - this.senderSp = senderSp; - this.initialInfo = initialInfo; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value frameSizeValue = gen.operand(frameSize); - Value framePcValue = gen.operand(framePc); - Value senderSpValue = gen.operand(senderSp); - Value initialInfoValue = gen.operand(initialInfo); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitPushInterpreterFrame(frameSizeValue, framePcValue, senderSpValue, initialInfoValue); - } - - @NodeIntrinsic - public static native void pushInterpreterFrame(Word frameSize, Word framePc, Word senderSp, Word initialInfo); - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java deleted file mode 100644 index e0a25037e31..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import jdk.vm.ci.meta.JavaKind; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Saves all allocatable registers. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(SaveAllRegistersNode.class); - protected SaveRegistersOp saveRegistersOp; - - public SaveAllRegistersNode() { - super(TYPE, StampFactory.forKind(JavaKind.Long)); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - saveRegistersOp = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitSaveAllRegisters(); - } - - /** - * @return the map from registers to the stack locations in they are saved - */ - public SaveRegistersOp getSaveRegistersOp() { - assert saveRegistersOp != null : "saved registers op has not yet been created"; - return saveRegistersOp; - } - - /** - * @return a token that couples this node to an {@link UncommonTrapCallNode} so that the latter - * has access to the {@linkplain SaveRegistersOp#getMap register save map} - */ - @NodeIntrinsic - public static native long saveAllRegisters(); - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java index ba95b819b91..29da335efa6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_15; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; -@NodeInfo(cycles = CYCLES_15, size = SIZE_20) +@NodeInfo(cycles = CYCLES_8, size = SIZE_8) public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(SerialArrayRangeWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java index cf03b16b8e4..608b9b4c3dd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java @@ -23,13 +23,13 @@ package org.graalvm.compiler.hotspot.nodes; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.memory.address.AddressNode; -@NodeInfo(cycles = CYCLES_8, size = SIZE_3) +@NodeInfo(cycles = CYCLES_8, size = SIZE_4) public class SerialWriteBarrier extends ObjectWriteBarrier { public static final NodeClass TYPE = NodeClass.create(SerialWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java deleted file mode 100644 index 061dc110df3..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java +++ /dev/null @@ -1,57 +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.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.spi.Canonicalizable; -import org.graalvm.compiler.graph.spi.CanonicalizerTool; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; - -@NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value}, cycles = CYCLES_0, size = SIZE_0) -public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable, Node.ValueNumberable { - - public static final NodeClass TYPE = NodeClass.create(SnippetLocationProxyNode.class); - @Input(InputType.Unchecked) ValueNode location; - - public SnippetLocationProxyNode(ValueNode location) { - super(TYPE, StampFactory.object()); - this.location = location; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - return location.isAllowedUsageType(InputType.Association) ? location : this; - } - - @NodeIntrinsic - public static native GuardingNode location(Object location); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java index 3d285fcfce6..a7e28a9dcb6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java @@ -28,11 +28,10 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; import java.util.Arrays; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; @@ -43,8 +42,8 @@ import org.graalvm.compiler.nodes.ValueNode; 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.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; /** @@ -59,8 +58,8 @@ public final class StubForeignCallNode extends FixedWithNextNode implements LIRL protected final ForeignCallDescriptor descriptor; - public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(descriptor.getResultType()))); + public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, @InjectedNodeParameter Stamp stamp, ForeignCallDescriptor descriptor, ValueNode... arguments) { + super(TYPE, stamp); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java deleted file mode 100644 index 2cee5fc0185..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code implementing the uncommon trap logic. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public final class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(UncommonTrapCallNode.class); - @Input ValueNode trapRequest; - @Input ValueNode mode; - @Input SaveAllRegistersNode registerSaver; - protected final ForeignCallsProvider foreignCalls; - - public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest, ValueNode mode) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); - this.trapRequest = trapRequest; - this.mode = mode; - this.registerSaver = (SaveAllRegistersNode) registerSaver; - this.foreignCalls = foreignCalls; - } - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } - - public SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - /** - * Returns the node representing the exec_mode/unpack_kind used during this fetch_unroll_info - * call. - */ - public ValueNode getMode() { - return mode; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value trapRequestValue = gen.operand(trapRequest); - Value modeValue = gen.operand(getMode()); - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitUncommonTrapCall(trapRequestValue, modeValue, getSaveRegistersOp()); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native Word uncommonTrap(long registerSaver, int trapRequest, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java index 31cbf052bdb..b6905996f69 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java @@ -22,6 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; + +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -37,15 +41,15 @@ import org.graalvm.compiler.word.Word; import jdk.vm.ci.meta.Constant; -@NodeInfo +@NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) public final class EncodedSymbolNode extends FloatingNode implements Canonicalizable { public static final NodeClass TYPE = NodeClass.create(EncodedSymbolNode.class); @OptionalInput protected ValueNode value; - public EncodedSymbolNode(ValueNode value) { - super(TYPE, null); + public EncodedSymbolNode(@InjectedNodeParameter Stamp stamp, ValueNode value) { + super(TYPE, stamp); assert value != null; this.value = value; } @@ -61,6 +65,6 @@ public final class EncodedSymbolNode extends FloatingNode implements Canonicaliz return this; } - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic public static native Word encode(Object constant); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java index 48acc4c080e..aff5ce9b872 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java @@ -22,18 +22,21 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.InputType.Memory; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; +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; -@NodeInfo(cycles = CYCLES_3, size = SIZE_20) -public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable { +@NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {Memory}) +public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable, MemoryCheckpoint.Single { public static final NodeClass TYPE = NodeClass.create(InitializeKlassNode.class); @Input ValueNode value; @@ -56,4 +59,9 @@ public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implement public boolean canDeoptimize() { return true; } + + @Override + public LocationIdentity getLocationIdentity() { + return LocationIdentity.any(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java index 03d11fa9107..2630a60dcd3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java @@ -23,9 +23,8 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -43,6 +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.compiler.nodes.util.GraphUtil; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.meta.Constant; @@ -51,7 +51,7 @@ import jdk.vm.ci.meta.Value; /** * A call to the VM via a regular stub. */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_20) +@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_16) public class InitializeKlassStubCall extends AbstractMemoryCheckpoint implements LIRLowerable, Canonicalizable, DeoptimizingNode.DeoptBefore, MemoryCheckpoint.Single { public static final NodeClass TYPE = NodeClass.create(InitializeKlassStubCall.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java index 257fc5a7fca..2603e78cee4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -46,7 +46,7 @@ import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +@NodeInfo(cycles = CYCLES_4, size = SIZE_1) public class LoadConstantIndirectlyFixedNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadConstantIndirectlyFixedNode.class); @@ -56,14 +56,14 @@ public class LoadConstantIndirectlyFixedNode extends FixedWithNextNode implement protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyFixedNode(ValueNode value) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyFixedNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = action; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java index 10c3c9337aa..8758c02cba3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -45,7 +45,7 @@ import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +@NodeInfo(cycles = CYCLES_4, size = SIZE_1) public class LoadConstantIndirectlyNode extends FloatingNode implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadConstantIndirectlyNode.class); @@ -55,14 +55,14 @@ public class LoadConstantIndirectlyNode extends FloatingNode implements Canonica protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyNode(ValueNode value) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = action; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java index 1b8180b082c..dd427b1772a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -46,7 +46,7 @@ import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +@NodeInfo(cycles = CYCLES_4, size = SIZE_4) public class LoadMethodCountersIndirectlyNode extends FloatingNode implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadMethodCountersIndirectlyNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java index 290de38a039..f9ebc380e18 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java @@ -22,10 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; @@ -37,7 +35,9 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo(cycles = CYCLES_4, size = SIZE_4) public class LoadMethodCountersNode extends FloatingNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadMethodCountersNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java index 17a3e0e6a9e..73202626047 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java @@ -22,19 +22,19 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -@NodeInfo(cycles = CYCLES_3, size = SIZE_20) -public class ResolveConstantNode extends FloatingNode implements Lowerable { +@NodeInfo(cycles = CYCLES_4, size = SIZE_16) +public class ResolveConstantNode extends DeoptimizingFixedWithNextNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(ResolveConstantNode.class); @Input ValueNode value; @@ -64,4 +64,9 @@ public class ResolveConstantNode extends FloatingNode implements Lowerable { public HotSpotConstantLoadAction action() { return action; } + + @Override + public boolean canDeoptimize() { + return true; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java index 017feacf64d..6a6393b1990 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java @@ -23,9 +23,9 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -49,7 +49,7 @@ import jdk.vm.ci.meta.Value; /** * A call to the VM via a regular stub. */ -@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_20) +@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_16) public class ResolveConstantStubCall extends DeoptimizingStubCall implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(ResolveConstantStubCall.class); @@ -110,5 +110,4 @@ public class ResolveConstantStubCall extends DeoptimizingStubCall implements Can } gen.setResult(this, result); } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java index 6561da24de9..78458f26b38 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java @@ -22,21 +22,21 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.nodes.type.MethodCountersPointerStamp; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -@NodeInfo(cycles = CYCLES_3, size = SIZE_20) -public class ResolveMethodAndLoadCountersNode extends FloatingNode implements Lowerable { +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo(cycles = CYCLES_4, size = SIZE_16) +public class ResolveMethodAndLoadCountersNode extends DeoptimizingFixedWithNextNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(ResolveMethodAndLoadCountersNode.class); ResolvedJavaMethod method; @@ -60,4 +60,9 @@ public class ResolveMethodAndLoadCountersNode extends FloatingNode implements Lo public ValueNode getHub() { return hub; } + + @Override + public boolean canDeoptimize() { + return true; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java index faa0bd095a0..725e3736d8c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java @@ -22,11 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -45,10 +42,13 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.Value; + /** * A call to the VM via a regular stub. */ -@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_20) +@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_16) public class ResolveMethodAndLoadCountersStubCall extends DeoptimizingStubCall implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(ResolveMethodAndLoadCountersStubCall.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java index 9d5e015bf4c..c5c09718e6b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java @@ -22,7 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes.profiling; -import jdk.vm.ci.meta.ResolvedJavaMethod; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -34,14 +35,16 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -@NodeInfo +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo(cycles = CYCLES_IGNORED, cyclesRationale = "profiling should be ignored", size = SIZE_IGNORED, sizeRationale = "profiling should be ignored") public class ProfileNode extends DeoptimizingFixedWithNextNode implements Lowerable { public static class Options { @Option(help = "Control probabilistic profiling on AMD64", type = OptionType.Expert)// - public static final OptionValue ProbabilisticProfiling = new OptionValue<>(true); + public static final OptionKey ProbabilisticProfiling = new OptionKey<>(true); } public static final NodeClass TYPE = NodeClass.create(ProfileNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java index 4d63dea4a5d..d0fdcbc2867 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java @@ -22,15 +22,12 @@ */ package org.graalvm.compiler.hotspot.nodes.profiling; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; - import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -@NodeInfo(cycles = CYCLES_10, size = SIZE_50) +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo public class ProfileWithNotificationNode extends ProfileNode { public static final NodeClass TYPE = NodeClass.create(ProfileWithNotificationNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/HotSpotNarrowOopStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/HotSpotNarrowOopStamp.java new file mode 100644 index 00000000000..ae4e255de7e --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/HotSpotNarrowOopStamp.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.nodes.type; + +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.core.common.type.AbstractObjectStamp; +import org.graalvm.compiler.core.common.type.ObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; +import org.graalvm.compiler.nodes.type.NarrowOopStamp; + +import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; +import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + +public final class HotSpotNarrowOopStamp extends NarrowOopStamp { + private HotSpotNarrowOopStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull, CompressEncoding encoding) { + super(type, exactType, nonNull, alwaysNull, encoding); + } + + @Override + protected AbstractObjectStamp copyWith(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { + return new HotSpotNarrowOopStamp(type, exactType, nonNull, alwaysNull, getEncoding()); + } + + public static Stamp compressed(AbstractObjectStamp stamp, CompressEncoding encoding) { + return new HotSpotNarrowOopStamp(stamp.type(), stamp.isExactType(), stamp.nonNull(), stamp.alwaysNull(), encoding); + } + + @Override + public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { + try { + HotSpotMemoryAccessProvider hsProvider = (HotSpotMemoryAccessProvider) provider; + return hsProvider.readNarrowOopConstant(base, displacement); + } catch (IllegalArgumentException e) { + return null; + } + } + + @Override + public JavaConstant asConstant() { + if (alwaysNull()) { + return HotSpotCompressedNullConstant.COMPRESSED_NULL; + } else { + return null; + } + } + + @Override + public boolean isCompatible(Constant other) { + if (other instanceof HotSpotObjectConstant) { + return ((HotSpotObjectConstant) other).isCompressed(); + } + return true; + } + + public static Stamp mkStamp(CompressionOp op, Stamp input, CompressEncoding encoding) { + switch (op) { + case Compress: + if (input instanceof ObjectStamp) { + // compressed oop + return HotSpotNarrowOopStamp.compressed((ObjectStamp) input, encoding); + } else if (input instanceof KlassPointerStamp) { + // compressed klass pointer + return ((KlassPointerStamp) input).compressed(encoding); + } + break; + case Uncompress: + if (input instanceof NarrowOopStamp) { + // oop + assert encoding.equals(((NarrowOopStamp) input).getEncoding()); + return ((NarrowOopStamp) input).uncompressed(); + } else if (input instanceof KlassPointerStamp) { + // metaspace pointer + assert encoding.equals(((KlassPointerStamp) input).getEncoding()); + return ((KlassPointerStamp) input).uncompressed(); + } + break; + } + throw GraalError.shouldNotReachHere(String.format("Unexpected input stamp %s", input)); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java index 51ef44ea120..b5af57d0251 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java @@ -24,11 +24,11 @@ package org.graalvm.compiler.hotspot.nodes.type; import java.util.Objects; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.hotspot.CompressEncoding; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; @@ -131,7 +131,7 @@ public final class KlassPointerStamp extends MetaspacePointerStamp { @Override public LIRKind getLIRKind(LIRKindTool tool) { if (isCompressed()) { - return ((HotSpotLIRKindTool) tool).getNarrowPointerKind(); + return tool.getNarrowPointerKind(); } else { return super.getLIRKind(tool); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java index 4db514de7e1..53a2298fb81 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java @@ -59,6 +59,11 @@ public abstract class MetaspacePointerStamp extends AbstractPointerStamp { return true; } + @Override + public Stamp join(Stamp other) { + return defaultPointerJoin(other); + } + @Override public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { throw GraalError.shouldNotReachHere("metaspace pointer has no Java type"); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java index bb5d0f71bdd..ff0ac313979 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java @@ -22,19 +22,20 @@ */ package org.graalvm.compiler.hotspot.phases; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; import static org.graalvm.compiler.nodes.NamedLocationIdentity.FINAL_LOCATION; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; 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.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; +import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.hotspot.replacements.HubGetClassNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -67,12 +68,10 @@ import jdk.vm.ci.meta.ResolvedJavaType; */ public class LoadJavaMirrorWithKlassPhase extends BasePhase { - private final int classMirrorOffset; private final CompressEncoding oopEncoding; - public LoadJavaMirrorWithKlassPhase(int classMirrorOffset, CompressEncoding oopEncoding) { - this.classMirrorOffset = classMirrorOffset; - this.oopEncoding = oopEncoding; + public LoadJavaMirrorWithKlassPhase(GraalHotSpotVMConfig config) { + this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null; } private ValueNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, JavaConstant constant) { @@ -85,13 +84,12 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase { if (type instanceof HotSpotResolvedObjectType) { ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph); - AddressNode address = graph.unique(new OffsetAddressNode(klass, ConstantNode.forLong(classMirrorOffset, graph))); - ValueNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, stamp)); + ValueNode getClass = graph.unique(new HubGetClassNode(metaAccess, klass)); if (((HotSpotObjectConstant) constant).isCompressed()) { - return CompressionNode.compress(read, oopEncoding); + return HotSpotCompressionNode.compress(getClass, oopEncoding); } else { - return read; + return getClass; } } else { /* @@ -114,7 +112,7 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase { } if (oopEncoding != null) { - stamp = NarrowOopStamp.compressed((AbstractObjectStamp) stamp, oopEncoding); + stamp = HotSpotNarrowOopStamp.compressed((AbstractObjectStamp) stamp, oopEncoding); } AddressNode address = graph.unique(new OffsetAddressNode(clazz, ConstantNode.forLong(typeField.offset(), graph))); ValueNode read = graph.unique(new FloatingReadNode(address, FINAL_LOCATION, null, stamp)); @@ -122,7 +120,7 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase { if (oopEncoding == null || ((HotSpotObjectConstant) constant).isCompressed()) { return read; } else { - return CompressionNode.uncompress(read, oopEncoding); + return HotSpotCompressionNode.uncompress(read, oopEncoding); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java index 84f0f33ecb5..9531171cf60 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java @@ -24,9 +24,11 @@ package org.graalvm.compiler.hotspot.phases; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.cfg.Loop; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugCounter; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -35,17 +37,30 @@ import org.graalvm.compiler.loop.phases.LoopTransformations; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractLocalNode; import org.graalvm.compiler.nodes.EntryMarkerNode; import org.graalvm.compiler.nodes.EntryProxyNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.extended.OSRLocalNode; +import org.graalvm.compiler.nodes.extended.OSRLockNode; +import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode; import org.graalvm.compiler.nodes.extended.OSRStartNode; +import org.graalvm.compiler.nodes.java.AccessMonitorNode; +import org.graalvm.compiler.nodes.java.MonitorEnterNode; +import org.graalvm.compiler.nodes.java.MonitorExitNode; +import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; @@ -53,6 +68,24 @@ import jdk.vm.ci.runtime.JVMCICompiler; public class OnStackReplacementPhase extends Phase { + public static class Options { + // @formatter:off + @Option(help = "Deoptimize OSR compiled code when the OSR entry loop is finished " + + "if there is no mature profile available for the rest of the method.", type = OptionType.Debug) + public static final OptionKey DeoptAfterOSR = new OptionKey<>(true); + @Option(help = "Support OSR compilations with locks. If DeoptAfterOSR is true we can per definition not have " + + "unbalaced enter/extis mappings. If DeoptAfterOSR is false insert artificial monitor enters after " + + "the OSRStart to have balanced enter/exits in the graph.", type = OptionType.Debug) + public static final OptionKey SupportOSRWithLocks = new OptionKey<>(true); + // @formatter:on + } + + private static final DebugCounter OsrWithLocksCount = Debug.counter("OSRWithLocks"); + + private static boolean supportOSRWithLocks(OptionValues options) { + return Options.SupportOSRWithLocks.getValue(options); + } + @Override protected void run(StructuredGraph graph) { if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) { @@ -61,10 +94,29 @@ public class OnStackReplacementPhase extends Phase { assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty(); return; } - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement initial"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI()); + EntryMarkerNode osr; int maxIterations = -1; int iterations = 0; + + final EntryMarkerNode originalOSRNode = getEntryMarker(graph); + final LoopBeginNode originalOSRLoop = osrLoop(originalOSRNode); + final boolean currentOSRWithLocks = osrWithLocks(originalOSRNode); + + if (originalOSRLoop == null) { + /* + * OSR with Locks: We do not have an OSR loop for the original OSR bci. Therefore we + * cannot decide where to deopt and which framestate will be used. In the worst case the + * framestate of the OSR entry would be used. + */ + throw new PermanentBailoutException("OSR compilation without OSR entry loop."); + } + + if (!supportOSRWithLocks(graph.getOptions()) && currentOSRWithLocks) { + throw new PermanentBailoutException("OSR with locks disabled."); + } + do { osr = getEntryMarker(graph); LoopsData loops = new LoopsData(graph); @@ -73,6 +125,7 @@ public class OnStackReplacementPhase extends Phase { if (l == null) { break; } + iterations++; if (maxIterations == -1) { maxIterations = l.getDepth(); @@ -91,7 +144,7 @@ public class OnStackReplacementPhase extends Phase { proxy.replaceAndDelete(proxy.value()); } GraphUtil.removeFixedWithUnusedInputs(osr); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement loop peeling result"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result"); } while (true); FrameState osrState = osr.stateAfter(); @@ -104,26 +157,81 @@ public class OnStackReplacementPhase extends Phase { graph.setStart(osrStart); osrStart.setStateAfter(osrState); - for (int i = 0; i < osrState.localsSize(); i++) { - ValueNode value = osrState.localAt(i); + Debug.dump(Debug.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). */ - proxy.replaceAndDelete(graph.addOrUnique(new OSRLocalNode(i, proxy.stamp().unrestricted()))); + Stamp s = proxy.stamp().unrestricted(); + AbstractLocalNode osrLocal = null; + if (i >= localsSize) { + osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, s)); + } else { + osrLocal = graph.addOrUnique(new OSRLocalNode(i, s)); + } + proxy.replaceAndDelete(osrLocal); } else { assert value == null || value instanceof OSRLocalNode; } } + osr.replaceAtUsages(InputType.Guard, osrStart); - assert osr.usages().isEmpty(); - + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies"); GraphUtil.killCFG(start); - - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result"); + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result"); new DeadCodeEliminationPhase(Required).apply(graph); + + if (currentOSRWithLocks) { + OsrWithLocksCount.increment(); + 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); + } + Debug.dump(Debug.DETAILED_LEVEL, graph, "After inserting OSR monitor enters"); + /* + * Ensure balanced monitorenter - monitorexit + * + * Ensure that there is no monitor exit without a monitor enter in the graph. If there + * is one this can only be done by bytecode as we have the monitor enter before the OSR + * loop but the exit in a path of the loop that must be under a condition, else it will + * throw an IllegalStateException anyway in the 2.iteration + */ + for (MonitorExitNode exit : graph.getNodes(MonitorExitNode.TYPE)) { + MonitorIdNode id = exit.getMonitorId(); + if (id.usages().filter(MonitorEnterNode.class).count() != 1) { + throw new PermanentBailoutException("Unbalanced monitor enter-exit in OSR compilation with locks. Object is locked before the loop but released inside the loop."); + } + } + } + Debug.dump(Debug.DETAILED_LEVEL, graph, "OnStackReplacement result"); + new DeadCodeEliminationPhase(Required).apply(graph); + /* + * There must not be any parameter nodes left after OSR compilation. + */ + assert graph.getNodes(ParameterNode.TYPE).count() == 0 : "OSR Compilation contains references to parameters."; } private static EntryMarkerNode getEntryMarker(StructuredGraph graph) { @@ -135,15 +243,26 @@ public class OnStackReplacementPhase extends Phase { if (osrNodes.count() > 1) { throw new GraalError("Multiple OnStackReplacementNodes generated"); } - if (osr.stateAfter().locksSize() != 0) { - throw new PermanentBailoutException("OSR with locks not supported"); - } if (osr.stateAfter().stackSize() != 0) { throw new PermanentBailoutException("OSR with stack entries not supported: %s", osr.stateAfter().toString(Verbosity.Debugger)); } return osr; } + private static LoopBeginNode osrLoop(EntryMarkerNode osr) { + // Check that there is an OSR loop for the OSR begin + LoopsData loops = new LoopsData(osr.graph()); + Loop l = loops.getCFG().getNodeToBlock().get(osr).getLoop(); + if (l == null) { + return null; + } + return (LoopBeginNode) l.getHeader().getBeginNode(); + } + + private static boolean osrWithLocks(EntryMarkerNode osr) { + return osr.stateAfter().locksSize() != 0; + } + @Override public float codeSizeIncrease() { return 5.0f; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java index a252994fe7b..f837b9127e6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java @@ -35,8 +35,8 @@ import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; +import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; -import org.graalvm.compiler.nodes.java.LoweredCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; @@ -63,8 +63,8 @@ public class WriteBarrierAdditionPhase extends Phase { } else if (n instanceof LoweredAtomicReadAndWriteNode) { LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n; addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph); - } else if (n instanceof LoweredCompareAndSwapNode) { - addCASBarriers((LoweredCompareAndSwapNode) n, graph); + } else if (n instanceof AbstractCompareAndSwapNode) { + addCASBarriers((AbstractCompareAndSwapNode) n, graph); } else if (n instanceof ArrayRangeWriteNode) { ArrayRangeWriteNode node = (ArrayRangeWriteNode) n; if (node.isObjectArray()) { @@ -116,7 +116,7 @@ public class WriteBarrierAdditionPhase extends Phase { case PRECISE: boolean precise = barrierType == BarrierType.PRECISE; if (config.useG1GC) { - if (!node.isInitialization()) { + if (!node.getLocationIdentity().isInit()) { addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph); } addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph); @@ -150,7 +150,7 @@ public class WriteBarrierAdditionPhase extends Phase { } } - private void addCASBarriers(LoweredCompareAndSwapNode node, StructuredGraph graph) { + private void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph) { BarrierType barrierType = node.getBarrierType(); switch (barrierType) { case NONE: diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java index 1cd9421ffe6..639292f3772 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.hotspot.nodes.ArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.ObjectWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.LoopBeginNode; @@ -40,7 +41,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; -import org.graalvm.compiler.nodes.java.LoweredCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.HeapAccess; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; @@ -48,6 +49,7 @@ import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.Phase; /** @@ -73,6 +75,12 @@ public class WriteBarrierVerificationPhase extends Phase { private void processWrites(StructuredGraph graph) { for (Node node : graph.getNodes()) { if (isObjectWrite(node) || isObjectArrayRangeWrite(node)) { + if (node instanceof WriteNode) { + WriteNode writeNode = (WriteNode) node; + if (StampTool.isPointerAlwaysNull(writeNode.value())) { + continue; + } + } validateWrite(node); } } @@ -92,7 +100,7 @@ public class WriteBarrierVerificationPhase extends Phase { while (iterator.hasNext()) { Node currentNode = iterator.next(); if (isSafepoint(currentNode)) { - throw new AssertionError("Write barrier must be present " + write); + throw new AssertionError("Write barrier must be present " + write.toString(Verbosity.All) + " / " + write.inputs()); } if (useG1GC()) { if (!(currentNode instanceof G1PostWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode))) { @@ -114,7 +122,13 @@ public class WriteBarrierVerificationPhase extends Phase { private boolean hasAttachedBarrier(FixedWithNextNode node) { final Node next = node.next(); final Node previous = node.predecessor(); - final boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization()); + boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization()); + if (node instanceof WriteNode) { + WriteNode writeNode = (WriteNode) node; + if (writeNode.getLocationIdentity().isInit()) { + validatePreBarrier = false; + } + } if (isObjectWrite(node)) { return (isObjectBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isObjectBarrier(node, previous)); } else if (isObjectArrayRangeWrite(node)) { @@ -150,6 +164,10 @@ public class WriteBarrierVerificationPhase extends Phase { } private static boolean isSafepoint(Node node) { + if (node instanceof FixedAccessNode) { + // Implicit null checks on reads or writes do not count. + return false; + } /* * LoopBegin nodes are also treated as safepoints since a bottom-up analysis is performed * and loop safepoints are placed before LoopEnd nodes. Possible elimination of write @@ -161,8 +179,8 @@ public class WriteBarrierVerificationPhase extends Phase { private static ValueNode getValueWritten(FixedWithNextNode write) { if (write instanceof WriteNode) { return ((WriteNode) write).value(); - } else if (write instanceof LoweredCompareAndSwapNode) { - return ((LoweredCompareAndSwapNode) write).getNewValue(); + } else if (write instanceof LogicCompareAndSwapNode) { + return ((LogicCompareAndSwapNode) write).getNewValue(); } else if (write instanceof LoweredAtomicReadAndWriteNode) { return ((LoweredAtomicReadAndWriteNode) write).getNewValue(); } else { @@ -171,10 +189,10 @@ public class WriteBarrierVerificationPhase extends Phase { } private static boolean validateBarrier(FixedAccessNode write, ObjectWriteBarrier barrier) { - assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write; + assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write; if (!barrier.usePrecise()) { if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) { - return ((OffsetAddressNode) barrier.getAddress()).getBase() == ((OffsetAddressNode) write.getAddress()).getBase(); + return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) write.getAddress()).getBase()); } } return barrier.getAddress() == write.getAddress(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java index 8f1efa35b38..fbf81adcc66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java @@ -31,8 +31,9 @@ import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; 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; @@ -44,11 +45,11 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { public static class Options { // @formatter:off @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningDepthToSizeRate = new OptionValue<>(2.5); + public static final OptionKey AOTInliningDepthToSizeRate = new OptionKey<>(2.5); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningSizeMaximum = new OptionValue<>(300); + public static final OptionKey AOTInliningSizeMaximum = new OptionKey<>(300); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningSizeMinimum = new OptionValue<>(50); + public static final OptionKey AOTInliningSizeMinimum = new OptionKey<>(50); // @formatter:on } @@ -56,8 +57,8 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { super(hints); } - protected double maxInliningSize(int inliningDepth) { - return Math.max(Options.AOTInliningSizeMaximum.getValue() / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue()), Options.AOTInliningSizeMinimum.getValue()); + protected double maxInliningSize(int inliningDepth, OptionValues options) { + return Math.max(Options.AOTInliningSizeMaximum.getValue(options) / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue(options)), Options.AOTInliningSizeMinimum.getValue(options)); } @Override @@ -74,7 +75,8 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { final double probability = invocation.probability(); final double relevance = invocation.relevance(); - if (InlineEverything.getValue()) { + OptionValues options = info.graph().getOptions(); + if (InlineEverything.getValue(options)) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); return true; } @@ -92,12 +94,12 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { double inliningBonus = getInliningBonus(info); int nodes = info.determineNodeCount(); - if (nodes < TrivialInliningSize.getValue() * inliningBonus) { + if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes); return true; } - double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth) * inliningBonus)); + double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus)); if (nodes <= maximumNodes) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus, nodes, maximumNodes); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java index caa04c2c979..86712f186f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,160 +22,30 @@ */ package org.graalvm.compiler.hotspot.phases.aot; -import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; +import static org.graalvm.util.CollectionsUtil.anyMatch; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map.Entry; +import java.util.Iterator; +import java.util.List; import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; +import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.graph.MergeableState; +import org.graalvm.compiler.phases.graph.PostOrderNodeIterator; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ResolvedJavaType; public class EliminateRedundantInitializationPhase extends BasePhase { - /** - * Find blocks with class initializing nodes for the class identified the by the constant node. - * Return the map of a block to a list of initializing nodes in that block. - * - * @param cfg an instance of the {@link ControlFlowGraph}. - * @param constant common input to the instances of {@link InitializeKlassNode}. - * @return map of blocks to lists of initializing nodes. - */ - private static HashMap> findBlocksWithInitializers(ControlFlowGraph cfg, ConstantNode constant) { - // node is ConstantNode representing a metaspace constant (a klass reference). - // InitializeKlassNodes for the same class would share the same ConstantNode input. - NodeIterable initializers = constant.usages().filter(InitializeKlassNode.class); - // Map the found nodes to blocks - HashMap> blockToInits = new HashMap<>(); - for (Node i : initializers) { - Block b = cfg.blockFor(i); - ArrayList initsInBlock = blockToInits.get(b); - if (initsInBlock == null) { - initsInBlock = new ArrayList<>(); - } - initsInBlock.add(i); - blockToInits.put(b, initsInBlock); - } - return blockToInits; - } - - /** - * Process the block-to-initializers map and produce a list of blocks that contain more than one - * instance of {@link InitializeKlassNode}. - * - * @param blockToInits a map of blocks to lists of {@link InitializeKlassNode} instances. - * @return list of blocks that contain multiple instances of {@link InitializeKlassNode}. - */ - private static ArrayList findBlocksWithMultipleInitializers(HashMap> blockToInits) { - ArrayList result = new ArrayList<>(); - // Select the blocks from the blocksToInits map that have more than one InitializeKlassNode - for (Entry> e : blockToInits.entrySet()) { - if (e.getValue().size() > 1) { - result.add(e.getKey()); - } - } - return result; - } - - /** - * Iterate through blocks with multiple instances of {@link InitializeKlassNode} and identify - * redundant instances. Remove redundant instances from the block-to-list-of-initializer map. - * - * @param blockToInits a map of blocks to lists of {@link InitializeKlassNode} instances. - * @param blocksWithMultipleInits a list of blocks that contain multiple instances of - * {@link InitializeKlassNode}. - * @param constant common input to the instances of {@link InitializeKlassNode}. - * @return list of {@link InitializeKlassNode} instances that can be removed. - */ - private static ArrayList findRedundantLocalInitializers(HashMap> blockToInits, ArrayList blocksWithMultipleInits, ConstantNode constant) { - ArrayList result = new ArrayList<>(); - for (Block b : blocksWithMultipleInits) { - // First initializer for our constant in the block - InitializeKlassNode first = null; - for (Node n : b.getNodes()) { - if (n instanceof InitializeKlassNode) { - InitializeKlassNode i = (InitializeKlassNode) n; - if (i.value() == constant) { - if (first == null) { - // First instance of {@link InitializeKlassNode} stays. - first = i; - } else { - // All the following instances of {@link InitializeKlassNode} can be - // removed. - result.add(i); - } - } - } - } - assert first != null; - - // Replace the entry in the initsInBlock map to contain just a single initializer - ArrayList initsInBlock = new ArrayList<>(); - initsInBlock.add(first); - blockToInits.put(b, initsInBlock); - } - return result; - } - - /** - * Find cases when one {@link InitializeKlassNode} instance dominates another. The dominated - * instance can be removed. - * - * @param blockToInits a map of blocks to lists of {@link InitializeKlassNode} instances. - * @return list of {@link InitializeKlassNode} instances that can be removed. - */ - private static ArrayList findRedundantGlobalInitializers(HashMap> blockToInits) { - ArrayList result = new ArrayList<>(); - for (Entry> e : blockToInits.entrySet()) { - Block currentBlock = e.getKey(); - ArrayList nodesInCurrent = e.getValue(); - if (nodesInCurrent != null) { // if the list is null, the initializer has already been - // eliminated. - for (Block d : currentBlock.getDominated()) { - ArrayList nodesInDominated = blockToInits.get(d); - if (nodesInDominated != null) { // if the list is null, the initializer has - // already been eliminated. - assert nodesInDominated.size() == 1; - Node n = nodesInDominated.iterator().next(); - result.add(n); - blockToInits.put(d, null); - } - } - } - } - return result; - } - - /** - * Compute the list of redundant {@link InitializeKlassNode} instances that have the common - * {@link ConstantNode}. - * - * @param cfg an instance of the {@link ControlFlowGraph}. - * @param constant common input to the instances of {@link InitializeKlassNode}. - * @return list of {@link InitializeKlassNode} instances that can be removed. - */ - private static ArrayList processConstantNode(ControlFlowGraph cfg, ConstantNode constant) { - HashMap> blockToInits = findBlocksWithInitializers(cfg, constant); - ArrayList blocksWithMultipleInits = findBlocksWithMultipleInitializers(blockToInits); - ArrayList redundantInits = findRedundantLocalInitializers(blockToInits, blocksWithMultipleInits, constant); - // At this point each block has at most one initializer for this constant - if (blockToInits.size() > 1) { - redundantInits.addAll(findRedundantGlobalInitializers(blockToInits)); - } - return redundantInits; - } - /** * Find each {@link Invoke} that has a corresponding {@link InitializeKlassNode}. These * {@link InitializeKlassNode} are redundant and are removed. @@ -191,26 +61,176 @@ public class EliminateRedundantInitializationPhase extends BasePhase redundantInits = findRedundantInits(graph); + for (InitializeKlassNode n : redundantInits) { + graph.removeFixed(n); + } + } + /** * Find {@link InitializeKlassNode} instances that can be removed because there is an existing * dominating initialization. * - * @param graph the program graph. + * @param graph the program graph */ - private static void removeRedundantInits(StructuredGraph graph) { - // Create cfg, we need blocks and dominators. - ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, false); - ArrayList redundantInits = new ArrayList<>(); - for (ConstantNode node : getConstantNodes(graph)) { - Constant constant = node.asConstant(); - if (constant instanceof HotSpotMetaspaceConstant) { - redundantInits.addAll(processConstantNode(cfg, node)); + private static List findRedundantInits(StructuredGraph graph) { + EliminateRedundantInitializationIterator i = new EliminateRedundantInitializationIterator(graph.start(), new InitializedTypes()); + i.apply(); + return i.getRedundantInits(); + } + + /** + * State for {@link EliminateRedundantInitializationIterator}. + */ + private static class InitializedTypes extends MergeableState implements Cloneable { + private EconomicSet types; + + InitializedTypes() { + types = EconomicSet.create(); + } + + private InitializedTypes(EconomicSet types) { + this.types = types; + } + + @Override + public InitializedTypes clone() { + return new InitializedTypes(EconomicSet.create(types)); + } + + public boolean contains(ResolvedJavaType type) { + if (type.isInterface()) { + // Check for exact match for interfaces + return types.contains(type); + } + // For other types see if there is the same type or a subtype + return anyMatch(types, t -> type.isAssignableFrom(t)); + } + + public void add(ResolvedJavaType type) { + types.add(type); + } + + /** + * Merge two given types. Interfaces have to be the same to merge successfully. For other + * types the answer is the LCA. + * + * @param a initialized type + * @param b initialized type + * @return lowest common type that is initialized if either a or b are initialized, null if + * no such type exists. + */ + private static ResolvedJavaType merge(ResolvedJavaType a, ResolvedJavaType b) { + // We want exact match for interfaces + if (a.isInterface() || b.isInterface()) { + if (a.equals(b)) { + return a; + } else { + return null; + } + } else { + // And LCA for other types + ResolvedJavaType c = a.findLeastCommonAncestor(b); + if (c.isJavaLangObject()) { + // Not a very useful type, always initialized, don't pollute the sets. + return null; + } + return c; } } - // Remove redundant instances of {@link InitializeKlassNode} from the graph. - for (Node n : redundantInits) { - graph.removeFixed((FixedWithNextNode) n); + + /** + * Merge two sets of types. Essentially a computation of the LCA for each element of the + * cartesian product of the input sets. Interfaces have to match exactly. + * + * @param a set of initialized types + * @param b set of initialized types + * @return set of common types that would be initialized if types in either a or b are + * initialized + */ + private static EconomicSet merge(EconomicSet a, EconomicSet b) { + EconomicSet c = EconomicSet.create(); + for (ResolvedJavaType ta : a) { + for (ResolvedJavaType tb : b) { + ResolvedJavaType tc = merge(ta, tb); + if (tc != null) { + c.add(tc); + if (tc.isInterface()) { + // Interface is not going merge with anything else, so bail out early. + break; + } + } + } + } + return c; } + + @Override + public boolean merge(AbstractMergeNode merge, List withStates) { + for (InitializedTypes ts : withStates) { + types = merge(types, ts.types); + } + return true; + } + + protected static String toString(EconomicSet types) { + StringBuilder b = new StringBuilder(); + b.append("["); + Iterator i = types.iterator(); + while (i.hasNext()) { + ResolvedJavaType t = i.next(); + b.append(t.toString()); + if (i.hasNext()) { + b.append(","); + } + } + b.append("]"); + return b.toString(); + } + + @Override + public String toString() { + return toString(types); + } + } + + /** + * Do data flow analysis of class initializations. Collect redundant initialization nodes. + */ + private static class EliminateRedundantInitializationIterator extends PostOrderNodeIterator { + private List redundantInits = new ArrayList<>(); + + public List getRedundantInits() { + return redundantInits; + } + + EliminateRedundantInitializationIterator(FixedNode start, InitializedTypes initialState) { + super(start, initialState); + } + + @Override + protected void node(FixedNode node) { + if (node instanceof InitializeKlassNode) { + InitializeKlassNode i = (InitializeKlassNode) node; + Constant c = i.value().asConstant(); + assert c != null : "Klass should be a constant at this point"; + HotSpotMetaspaceConstant klass = (HotSpotMetaspaceConstant) c; + ResolvedJavaType t = klass.asResolvedJavaType(); + if (state.contains(t)) { + redundantInits.add(i); + } else { + state.add(t); + } + } + } + } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java index 2766877c02a..5f378740661 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java @@ -22,10 +22,12 @@ */ package org.graalvm.compiler.hotspot.phases.aot; +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates; import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; import java.util.HashSet; +import java.util.List; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; @@ -35,11 +37,13 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.ResolvedJavaType; +import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; @@ -49,14 +53,21 @@ import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.util.EconomicMap; public class ReplaceConstantNodesPhase extends BasePhase { private static final HashSet> builtIns = new HashSet<>(); + private final boolean verifyFingerprints; static { builtIns.add(Boolean.class); @@ -91,6 +102,14 @@ public class ReplaceConstantNodesPhase extends BasePhase { // @formatter:on } + private static boolean anyUsagesNeedReplacement(ConstantNode node) { + return node.usages().filter(n -> !isReplacementNode(n)).isNotEmpty(); + } + + private static boolean anyUsagesNeedReplacement(LoadMethodCountersNode node) { + return node.usages().filter(n -> !(n instanceof ResolveMethodAndLoadCountersNode)).isNotEmpty(); + } + private static boolean checkForBadFingerprint(HotSpotResolvedJavaType type) { if (type.isArray()) { if (type.getElementalType().isPrimitive()) { @@ -101,80 +120,223 @@ public class ReplaceConstantNodesPhase extends BasePhase { return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) == 0; } - private static void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) { + /** + * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection. + * + * @param graph + * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs + * resolution. + */ + private void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) { HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); if (type != null) { - if (checkForBadFingerprint(type)) { + if (verifyFingerprints && checkForBadFingerprint(type)) { throw new GraalError("Type with bad fingerprint: " + type); } - assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants"; - ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass(); - ValueNode replacement; - - if (type.isArray() && type.getComponentType().isPrimitive()) { - // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may - // omit the resolution call. - replacement = new LoadConstantIndirectlyNode(node); - } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) { - // If it's a supertype of or the same class that declares the top method, we are - // guaranteed to have it resolved already. If it's an interface, we just test for - // equality. - replacement = new LoadConstantIndirectlyNode(node); - } else if (builtIns.contains(type.mirror())) { - // Special case of klass constants that come from {@link BoxingSnippets}. - replacement = new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE); - } else { - replacement = new ResolveConstantNode(node); + replaceWithInitialization(graph, node); + if (anyUsagesNeedReplacement(node)) { + replaceWithResolution(graph, node); } - - node.replaceAtUsages(graph.addOrUnique(replacement), n -> !isReplacementNode(n)); } else { throw new GraalError("Unsupported metaspace constant type: " + type); } } + /** + * Find the lowest dominating {@link FixedWithNextNode} before given node. + * + * @param graph + * @param node + * @return the last {@link FixedWithNextNode} that is scheduled before node. + */ + private static FixedWithNextNode findFixedWithNextBefore(StructuredGraph graph, Node node) { + ScheduleResult schedule = graph.getLastSchedule(); + NodeMap nodeToBlock = schedule.getNodeToBlockMap(); + BlockMap> blockToNodes = schedule.getBlockToNodesMap(); + + Block block = nodeToBlock.get(node); + FixedWithNextNode result = null; + for (Node n : blockToNodes.get(block)) { + if (n instanceof FixedWithNextNode) { + result = (FixedWithNextNode) n; + } + if (n.equals(node)) { + break; + } + } + assert result != null; + return result; + } + + /** + * Try to find dominating {@link InitializeKlassNode} that can be reused. + * + * @param graph + * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs + * resolution. + */ + private static void replaceWithInitialization(StructuredGraph graph, ConstantNode node) { + ScheduleResult schedule = graph.getLastSchedule(); + NodeMap nodeToBlock = schedule.getNodeToBlockMap(); + BlockMap> blockToNodes = schedule.getBlockToNodesMap(); + + EconomicMap blockToInit = EconomicMap.create(); + for (Node n : node.usages().filter(InitializeKlassNode.class)) { + blockToInit.put(nodeToBlock.get(n), n); + } + for (Node use : node.usages().filter(n -> !isReplacementNode(n)).snapshot()) { + boolean replaced = false; + Block b = nodeToBlock.get(use); + InitializeKlassNode i = (InitializeKlassNode) blockToInit.get(b); + if (i != null) { + // There is an initialization in the same block as the use, look if the use is + // scheduled after it. + for (Node n : blockToNodes.get(b)) { + if (n.equals(use)) { + // Usage is before initialization, can't use it + break; + } + if (n.equals(i)) { + use.replaceFirstInput(node, i); + replaced = true; + break; + } + } + } + if (!replaced) { + // Look for dominating blocks that have initializations + for (Block d : blockToInit.getKeys()) { + if (strictlyDominates(d, b)) { + use.replaceFirstInput(node, blockToInit.get(d)); + break; + } + } + } + } + } + + /** + * Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} or + * {@link ResolveConstantNode}. + * + * @param graph + * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs + * resolution. + */ + private static void replaceWithResolution(StructuredGraph graph, ConstantNode node) { + HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); + ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass(); + ValueNode replacement; + + if (type.isArray() && type.getComponentType().isPrimitive()) { + // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may + // omit the resolution call. + replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node)); + } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) { + // If it's a supertype of or the same class that declares the top method, we are + // guaranteed to have it resolved already. If it's an interface, we just test for + // equality. + replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node)); + } else { + FixedWithNextNode fixedReplacement; + if (builtIns.contains(type.mirror())) { + // Special case of klass constants that come from {@link BoxingSnippets}. + fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE)); + } else { + fixedReplacement = graph.add(new ResolveConstantNode(node)); + } + graph.addAfterFixed(findFixedWithNextBefore(graph, node), fixedReplacement); + replacement = fixedReplacement; + } + node.replaceAtUsages(replacement, n -> !isReplacementNode(n)); + } + + /** + * Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we + * support only strings. + * + * @param graph + * @param node {@link ConstantNode} containing a {@link HotSpotObjectConstant} that needs + * resolution. + */ private static void handleHotSpotObjectConstant(StructuredGraph graph, ConstantNode node) { HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant(); HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType(); if (type.mirror().equals(String.class)) { assert !constant.isCompressed() : "No support for replacing compressed oop constants"; - ValueNode replacement = graph.unique(new ResolveConstantNode(node)); + FixedWithNextNode replacement = graph.add(new ResolveConstantNode(node)); + graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement); node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode)); } else { throw new GraalError("Unsupported object constant type: " + type); } } + /** + * Replace {@link LoadMethodCountersNode} with indirect load + * {@link ResolveMethodAndLoadCountersNode}, expose a klass constant of the holder. + * + * @param graph + * @param node + * @param context + */ private static void handleLoadMethodCounters(StructuredGraph graph, LoadMethodCountersNode node, PhaseContext context) { ResolvedJavaType type = node.getMethod().getDeclaringClass(); Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull()); ConstantReflectionProvider constantReflection = context.getConstantReflection(); ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph); - ValueNode replacement = graph.unique(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint)); + FixedWithNextNode replacement = graph.add(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint)); + graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement); node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode)); } + /** + * Replace {@link LoadMethodCountersNode} with {@link ResolveMethodAndLoadCountersNode}, expose + * klass constants. + * + * @param graph + * @param context + */ + private static void replaceLoadMethodCounters(StructuredGraph graph, PhaseContext context) { + new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); + for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { + if (anyUsagesNeedReplacement(node)) { + handleLoadMethodCounters(graph, node, context); + } + } + } + + /** + * Replace object and klass constants with resolution nodes or reuse preceding initializations. + * + * @param graph + */ + private void replaceKlassesAndObjects(StructuredGraph graph) { + new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); + + for (ConstantNode node : getConstantNodes(graph)) { + Constant constant = node.asConstant(); + if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) { + handleHotSpotMetaspaceConstant(graph, node); + } else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) { + handleHotSpotObjectConstant(graph, node); + } + } + } + @Override protected void run(StructuredGraph graph, PhaseContext context) { // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass // constants. - for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { - handleLoadMethodCounters(graph, node, context); - } + replaceLoadMethodCounters(graph, context); // Replace object and klass constants (including the ones added in the previous pass) with // resolution nodes. - for (ConstantNode node : getConstantNodes(graph)) { - Constant constant = node.asConstant(); - if (constant instanceof HotSpotMetaspaceConstant) { - handleHotSpotMetaspaceConstant(graph, node); - } else if (constant instanceof HotSpotObjectConstant) { - handleHotSpotObjectConstant(graph, node); - } - } + replaceKlassesAndObjects(graph); } @Override @@ -182,4 +344,11 @@ public class ReplaceConstantNodesPhase extends BasePhase { return false; } + public ReplaceConstantNodesPhase() { + this(true); + } + + public ReplaceConstantNodesPhase(boolean verifyFingerprints) { + this.verifyFingerprints = verifyFingerprints; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java index e0fe3c71713..07576103017 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java @@ -36,17 +36,17 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.PhiNode; -import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -57,13 +57,13 @@ public class FinalizeProfileNodesPhase extends BasePhase { public static class Options { @Option(help = "Profile simple methods", type = OptionType.Expert)// - public static final OptionValue ProfileSimpleMethods = new OptionValue<>(true); + public static final OptionKey ProfileSimpleMethods = new OptionKey<>(true); @Option(help = "Maximum number of nodes in a graph for a simple method", type = OptionType.Expert)// - public static final OptionValue SimpleMethodGraphSize = new OptionValue<>(256); + public static final OptionKey SimpleMethodGraphSize = new OptionKey<>(256); @Option(help = "Maximum number of calls in a simple method", type = OptionType.Expert)// - public static final OptionValue SimpleMethodCalls = new OptionValue<>(1); + public static final OptionKey SimpleMethodCalls = new OptionKey<>(1); @Option(help = "Maximum number of indirect calls in a simple moethod", type = OptionType.Expert)// - public static final OptionValue SimpleMethodIndirectCalls = new OptionValue<>(0); + public static final OptionKey SimpleMethodIndirectCalls = new OptionKey<>(0); } @@ -88,12 +88,12 @@ public class FinalizeProfileNodesPhase extends BasePhase { // Hacky heuristic to determine whether we want any profiling in this method. // The heuristic is applied after the graph is fully formed and before the first lowering. private static boolean simpleMethodHeuristic(StructuredGraph graph) { - if (Options.ProfileSimpleMethods.getValue()) { + if (Options.ProfileSimpleMethods.getValue(graph.getOptions())) { return false; } // Check if the graph is smallish.. - if (graph.getNodeCount() > Options.SimpleMethodGraphSize.getValue()) { + if (graph.getNodeCount() > Options.SimpleMethodGraphSize.getValue(graph.getOptions())) { return false; } @@ -103,7 +103,7 @@ public class FinalizeProfileNodesPhase extends BasePhase { } // Check if method has calls - if (graph.getNodes().filter(InvokeNode.class).count() > Options.SimpleMethodCalls.getValue()) { + if (graph.getNodes().filter(InvokeNode.class).count() > Options.SimpleMethodCalls.getValue(graph.getOptions())) { return false; } @@ -160,7 +160,7 @@ public class FinalizeProfileNodesPhase extends BasePhase { } assignInlineeInvokeFrequencies(graph); - if (ProfileNode.Options.ProbabilisticProfiling.getValue()) { + if (ProfileNode.Options.ProbabilisticProfiling.getValue(graph.getOptions())) { assignRandomSources(graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java index 2240b335ed3..e525e6c7942 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY; import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; @@ -40,9 +39,11 @@ import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; -import org.graalvm.compiler.word.Pointer; +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.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; @@ -59,7 +60,12 @@ public class AESCryptSubstitutions { static final long kOffset; static final long lastKeyOffset; static final Class AESCryptClass; - static final int AES_BLOCK_SIZE_IN_BYTES; + + /** + * The AES block size is a constant 128 bits as defined by the + * standard. + */ + static final int AES_BLOCK_SIZE_IN_BYTES = 16; static { try { @@ -70,9 +76,6 @@ public class AESCryptSubstitutions { AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl); kOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("K")); lastKeyOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("lastKey")); - // Thankfully the AES block size is a constant (128 bits) and so we don't need to - // reflect on com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE. - AES_BLOCK_SIZE_IN_BYTES = 16; } catch (Exception ex) { throw new GraalError(ex); } @@ -118,15 +121,15 @@ public class AESCryptSubstitutions { private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt, boolean withOriginalKey) { checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass); - Object kObject = UnsafeLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any()); + Object kObject = RawLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any()); Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); - Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); - Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); + Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); + Word outAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); if (encrypt) { encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr); } else { if (withOriginalKey) { - Object lastKeyObject = UnsafeLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Object lastKeyObject = RawLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any()); Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); decryptBlockWithOriginalKeyStub(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, lastKeyAddr); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java index a99dbd4c535..516bada415e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.hotspot.nodes.StubStartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; @@ -53,15 +54,15 @@ public class AssertionSnippets implements Snippets { public static final ForeignCallDescriptor ASSERTION_VM_MESSAGE_C = new ForeignCallDescriptor("assertionVmMessageC", void.class, boolean.class, Word.class, long.class, long.class, long.class); @Snippet - public static void assertion(boolean value, @ConstantParameter String message) { - if (!value) { + public static void assertion(boolean condition, @ConstantParameter String message) { + if (!condition) { vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); } } @Snippet - public static void stubAssertion(boolean value, @ConstantParameter String message) { - if (!value) { + public static void stubAssertion(boolean condition, @ConstantParameter String message) { + if (!condition) { vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); } } @@ -74,14 +75,14 @@ public class AssertionSnippets implements Snippets { private final SnippetInfo assertion = snippet(AssertionSnippets.class, "assertion"); private final SnippetInfo stubAssertion = snippet(AssertionSnippets.class, "stubAssertion"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(AssertionNode assertionNode, LoweringTool tool) { StructuredGraph graph = assertionNode.graph(); Arguments args = new Arguments(graph.start() instanceof StubStartNode ? stubAssertion : assertion, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("value", assertionNode.value()); + args.add("condition", assertionNode.condition()); args.addConst("message", "failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")"); template(args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java index 1c1447d913a..8c8345e54aa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java @@ -38,6 +38,9 @@ import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; 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.vm.ci.meta.JavaKind; @@ -57,21 +60,27 @@ public class CRC32Substitutions { return config.crcTableAddress; } + /** + * Removed in 9. + */ @MethodSubstitution(optional = true) static int update(int crc, int b) { - final long crcTableRawAddress = GraalHotSpotVMConfigNode.crcTableAddress(); + final Pointer crcTableRawAddress = WordFactory.pointer(GraalHotSpotVMConfigNode.crcTableAddress()); int c = ~crc; int index = (b ^ c) & 0xFF; int offset = index << 2; - int result = Word.unsigned(crcTableRawAddress).readInt(offset); + int result = crcTableRawAddress.readInt(offset); result = result ^ (c >>> 8); return ~result; } + /** + * Removed in 9. + */ @MethodSubstitution(optional = true) static int updateBytes(int crc, byte[] buf, int off, int len) { - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } @@ -80,13 +89,16 @@ public class CRC32Substitutions { */ @MethodSubstitution(optional = true) static int updateBytes0(int crc, byte[] buf, int off, int len) { - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } + /** + * Removed in 9. + */ @MethodSubstitution(optional = true) static int updateByteBuffer(int crc, long addr, int off, int len) { - Word bufAddr = Word.unsigned(addr).add(off); + WordBase bufAddr = WordFactory.unsigned(addr).add(off); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } @@ -95,12 +107,12 @@ public class CRC32Substitutions { */ @MethodSubstitution(optional = true) static int updateByteBuffer0(int crc, long addr, int off, int len) { - Word bufAddr = Word.unsigned(addr).add(off); + WordBase bufAddr = WordFactory.unsigned(addr).add(off); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } - public static final ForeignCallDescriptor UPDATE_BYTES_CRC32 = new ForeignCallDescriptor("updateBytesCRC32", int.class, int.class, Word.class, int.class); + public static final ForeignCallDescriptor UPDATE_BYTES_CRC32 = new ForeignCallDescriptor("updateBytesCRC32", int.class, int.class, WordBase.class, int.class); @NodeIntrinsic(ForeignCallNode.class) - public static native int updateBytesCRC32(@ConstantNodeParameter ForeignCallDescriptor descriptor, int crc, Word buf, int length); + public static native int updateBytesCRC32(@ConstantNodeParameter ForeignCallDescriptor descriptor, int crc, WordBase buf, int length); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java index ab52ce28373..7e6d2960d70 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java @@ -31,7 +31,6 @@ import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; @@ -39,9 +38,11 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; -import org.graalvm.compiler.word.Pointer; +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.vm.ci.meta.JavaKind; @@ -82,7 +83,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); @@ -95,7 +96,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "implEncrypt") static int implEncrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); @@ -108,7 +109,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); @@ -121,7 +122,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int implDecrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); @@ -138,7 +139,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "decrypt") static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); @@ -154,7 +155,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "implDecrypt") static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); @@ -168,17 +169,17 @@ public class CipherBlockChainingSubstitutions { AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object aesCipher = getAESCryptClass().cast(embeddedCipher); - Object kObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); - Object rObject = UnsafeLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); + Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); + Object rObject = RawLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); Pointer rAddr = Word.objectToTrackedPointer(rObject).add(getArrayBaseOffset(JavaKind.Byte)); - Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); - Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); + Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); + Word outAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); if (encrypt) { encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength); } else { if (withOriginalKey) { - Object lastKeyObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any()); Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java index ea6af4de1f2..a385134ccb4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java @@ -22,11 +22,14 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.core.common.LocationIdentity; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; + import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -35,16 +38,19 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; +import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConvertNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.memory.ReadNode; 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.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -58,33 +64,40 @@ import jdk.vm.ci.meta.ResolvedJavaType; * handled by * {@link ReadNode#canonicalizeRead(ValueNode, AddressNode, LocationIdentity, CanonicalizerTool)}. */ -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { +@NodeInfo(cycles = CYCLES_1, size = SIZE_1) +public final class ClassGetHubNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode { public static final NodeClass TYPE = NodeClass.create(ClassGetHubNode.class); @Input protected ValueNode clazz; public ClassGetHubNode(ValueNode clazz) { - this(clazz, null); - } - - public ClassGetHubNode(ValueNode clazz, ValueNode guard) { - super(TYPE, KlassPointerStamp.klass(), (GuardingNode) guard); + super(TYPE, KlassPointerStamp.klass()); this.clazz = clazz; } - @Override - public Node canonical(CanonicalizerTool tool) { - if (tool.allUsagesAvailable() && hasNoUsages()) { + public static ValueNode create(ValueNode clazz, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable) { + return canonical(null, metaAccess, constantReflection, allUsagesAvailable, KlassPointerStamp.klass(), clazz); + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode clazz) { + ValueNode clazzValue = create(clazz, b.getMetaAccess(), b.getConstantReflection(), false); + b.push(JavaKind.Object, b.append(clazzValue)); + return true; + } + + public static ValueNode canonical(ClassGetHubNode classGetHubNode, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable, Stamp stamp, + ValueNode clazz) { + ClassGetHubNode self = classGetHubNode; + if (allUsagesAvailable && self != null && self.hasNoUsages()) { return null; } else { if (clazz.isConstant()) { - MetaAccessProvider metaAccess = tool.getMetaAccess(); if (metaAccess != null) { - ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(clazz.asJavaConstant()); + ResolvedJavaType exactType = constantReflection.asJavaType(clazz.asJavaConstant()); if (exactType.isPrimitive()) { - return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, metaAccess); + return ConstantNode.forConstant(stamp, JavaConstant.NULL_POINTER, metaAccess); } else { - return ConstantNode.forConstant(stamp(), tool.getConstantReflection().asObjectHub(exactType), metaAccess); + return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(exactType), metaAccess); } } } @@ -93,23 +106,31 @@ public final class ClassGetHubNode extends FloatingGuardedNode implements Lowera return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject()); } if (clazz instanceof HubGetClassNode) { - // replace _klass._java_mirror._klass -> _klass + // Replace: _klass._java_mirror._klass -> _klass return ((HubGetClassNode) clazz).getHub(); } - return this; + if (self == null) { + self = new ClassGetHubNode(clazz); + } + return self; } } + @Override + public Node canonical(CanonicalizerTool tool) { + return canonical(this, tool.getMetaAccess(), tool.getConstantReflection(), tool.allUsagesAvailable(), stamp(), clazz); + } + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); } @NodeIntrinsic - public static native KlassPointer readClass(Class clazz); + public static native KlassPointer readClass(Class clazzNonNull); - @NodeIntrinsic - public static native KlassPointer readClass(Class clazz, GuardingNode guard); + @NodeIntrinsic(PiNode.class) + public static native KlassPointer piCastNonNull(Object object, GuardingNode anchor); @Override public ValueNode getValue() { @@ -138,6 +159,14 @@ public final class ClassGetHubNode extends FloatingGuardedNode implements Lowera return false; } + /** + * There is more than one {@link java.lang.Class} value that has a NULL hub. + */ + @Override + public boolean mayNullCheckSkipConversion() { + return false; + } + @Override public boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) { assert op == Condition.EQ || op == Condition.NE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java index 301b03d12a6..9341f650207 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java @@ -26,7 +26,7 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.nio.ByteBuffer; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.type.DataPointerConstant; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java index f0608fdafbb..a870a65d4ce 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java @@ -39,12 +39,14 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.TargetDescription; @@ -63,7 +65,7 @@ public class HashCodeSnippets implements Snippets { // this code is independent from biased locking (although it does not look that way) final Word biasedLock = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); - if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(Word.unsigned(unlockedMask(INJECTED_VMCONFIG))))) { + if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(WordFactory.unsigned(unlockedMask(INJECTED_VMCONFIG))))) { int hash = (int) mark.unsignedShiftRight(identityHashCodeShift(INJECTED_VMCONFIG)).rawValue(); if (probability(FAST_PATH_PROBABILITY, hash != uninitializedIdentityHashCodeValue(INJECTED_VMCONFIG))) { return hash; @@ -76,8 +78,8 @@ public class HashCodeSnippets implements Snippets { private final SnippetInfo identityHashCodeSnippet = snippet(HashCodeSnippets.class, "identityHashCodeSnippet", HotSpotReplacementsUtil.MARK_WORD_LOCATION); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(IdentityHashCodeNode node, LoweringTool tool) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java index 8113802a62a..0a53eb454f1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; // JaCoCo Exclude @@ -78,7 +79,8 @@ public class HotSpotClassSubstitutions { // Class for primitive type return false; } else { - return klassIsArray(klass); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + return klassIsArray(klassNonNull); } } @@ -92,16 +94,18 @@ public class HotSpotClassSubstitutions { public static Class getSuperclass(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { - int accessFlags = klass.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + int accessFlags = klassNonNull.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION); if ((accessFlags & Modifier.INTERFACE) == 0) { - if (klassIsArray(klass)) { + if (klassIsArray(klassNonNull)) { return Object.class; } else { - KlassPointer superKlass = klass.readKlassPointer(klassSuperKlassOffset(INJECTED_VMCONFIG), KLASS_SUPER_KLASS_LOCATION); + KlassPointer superKlass = klassNonNull.readKlassPointer(klassSuperKlassOffset(INJECTED_VMCONFIG), KLASS_SUPER_KLASS_LOCATION); if (superKlass.isNull()) { return null; } else { - return readJavaMirror(superKlass); + KlassPointer superKlassNonNull = ClassGetHubNode.piCastNonNull(superKlass, SnippetAnchorNode.anchor()); + return HubGetClassNode.readClass(superKlassNonNull); } } } @@ -111,16 +115,13 @@ public class HotSpotClassSubstitutions { return null; } - public static Class readJavaMirror(KlassPointer klass) { - return PiNode.asNonNullClass(HubGetClassNode.readClass(klass)); - } - @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { - if (klassIsArray(klass)) { - return PiNode.asNonNullClass(klass.readObject(arrayKlassComponentMirrorOffset(INJECTED_VMCONFIG), ARRAY_KLASS_COMPONENT_MIRROR)); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + if (klassIsArray(klassNonNull)) { + return PiNode.asNonNullClass(klassNonNull.readObject(arrayKlassComponentMirrorOffset(INJECTED_VMCONFIG), ARRAY_KLASS_COMPONENT_MIRROR)); } } else { // Class for primitive type diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 90c34836d4e..37e7c1826a8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -22,15 +22,14 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP; import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.ObjectStamp; @@ -40,19 +39,17 @@ import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.CanonicalizableLocation; +import org.graalvm.compiler.nodes.CompressionNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.StoreHubNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; import org.graalvm.compiler.nodes.memory.Access; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; @@ -61,6 +58,8 @@ import org.graalvm.compiler.replacements.ReplacementsUtil; 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.vm.ci.code.CodeUtil; import jdk.vm.ci.code.Register; @@ -389,32 +388,23 @@ public class HotSpotReplacementsUtil { return config.klassLayoutHelperOffset; } - public static int readLayoutHelper(KlassPointer hub) { - // return hub.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); - GuardingNode anchorNode = SnippetAnchorNode.anchor(); - return loadKlassLayoutHelperIntrinsic(hub, anchorNode); - } - @NodeIntrinsic(value = KlassLayoutHelperNode.class) - public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object, GuardingNode anchor); - - @NodeIntrinsic(value = KlassLayoutHelperNode.class) - public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object); + public static native int readLayoutHelper(KlassPointer object); /** * Checks if class {@code klass} is an array. * * See: Klass::layout_helper_is_array * - * @param klass the class to be checked - * @return true if klass is an array, false otherwise + * @param klassNonNull the class to be checked + * @return true if klassNonNull is an array, false otherwise */ - public static boolean klassIsArray(KlassPointer klass) { + public static boolean klassIsArray(KlassPointer klassNonNull) { /* * The less-than check only works if both values are ints. We use local variables to make * sure these are still ints and haven't changed. */ - final int layoutHelper = readLayoutHelper(klass); + final int layoutHelper = readLayoutHelper(klassNonNull); final int layoutHelperNeutralValue = config(INJECTED_VMCONFIG).klassLayoutHelperNeutralValue; return (layoutHelper < layoutHelperNeutralValue); } @@ -479,6 +469,31 @@ public class HotSpotReplacementsUtil { return config.unlockedMask; } + @Fold + public static int monitorMask(@InjectedParameter GraalHotSpotVMConfig config) { + return config.monitorMask; + } + + @Fold + public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorOwner; + } + + @Fold + public static int objectMonitorRecursionsOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorRecursions; + } + + @Fold + public static int objectMonitorCxqOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorCxq; + } + + @Fold + public static int objectMonitorEntryListOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorEntryList; + } + /** * Mask for a biasable, locked or unlocked mark word. * @@ -545,7 +560,7 @@ public class HotSpotReplacementsUtil { } public static Word arrayStart(int[] a) { - return Word.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int))); + return WordFactory.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int))); } @Fold @@ -626,6 +641,14 @@ public class HotSpotReplacementsUtil { public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord"); + public static final LocationIdentity OBJECT_MONITOR_OWNER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_owner"); + + public static final LocationIdentity OBJECT_MONITOR_RECURSION_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_recursions"); + + public static final LocationIdentity OBJECT_MONITOR_CXQ_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_cxq"); + + public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList"); + @Fold public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.basicLockDisplacedHeaderOffset; @@ -680,17 +703,17 @@ public class HotSpotReplacementsUtil { public static Word loadWordFromObject(Object object, int offset) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any()); + return loadWordFromObjectIntrinsic(object, offset, LocationIdentity.any(), getWordKind()); } public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity); + return loadWordFromObjectIntrinsic(object, offset, identity, getWordKind()); } public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity); + return loadKlassFromObjectIntrinsic(object, offset, identity, getWordKind()); } /** @@ -703,17 +726,17 @@ public class HotSpotReplacementsUtil { return registerAsWord(register, true, false); } - @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = ReadRegisterNode.class) public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); - @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = WriteRegisterNode.class) public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); + @NodeIntrinsic(value = RawLoadNode.class) + private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind); - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); + @NodeIntrinsic(value = RawLoadNode.class) + private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind); @NodeIntrinsic(value = LoadHubNode.class) public static native KlassPointer loadHubIntrinsic(Object object); @@ -781,6 +804,8 @@ public class HotSpotReplacementsUtil { public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror"); + public static final LocationIdentity CLASS_MIRROR_HANDLE_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror handle"); + public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop"); @Fold diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java index 94724505f30..e22020218bb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java @@ -23,10 +23,10 @@ package org.graalvm.compiler.hotspot.replacements; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.ProfileContext; -import org.graalvm.compiler.options.EnumOptionValue; +import org.graalvm.compiler.options.EnumOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Options related to HotSpot snippets in this package. @@ -39,31 +39,34 @@ public class HotspotSnippetsOptions { // @formatter:off @Option(help = "If the probability that a type check will hit one the profiled types (up to " + "TypeCheckMaxHints) is below this value, the type check will be compiled without profiling info", type = OptionType.Expert) - public static final OptionValue TypeCheckMinProfileHitProbability = new OptionValue<>(0.5); + public static final OptionKey TypeCheckMinProfileHitProbability = new OptionKey<>(0.5); @Option(help = "The maximum number of profiled types that will be used when compiling a profiled type check. " + "Note that TypeCheckMinProfileHitProbability also influences whether profiling info is used in compiled type checks.", type = OptionType.Expert) - public static final OptionValue TypeCheckMaxHints = new OptionValue<>(2); + public static final OptionKey TypeCheckMaxHints = new OptionKey<>(2); @Option(help = "Use a VM runtime call to load and clear the exception object from the thread at the start of a compiled exception handler.", type = OptionType.Debug) - public static final OptionValue LoadExceptionObjectInVM = new OptionValue<>(false); + public static final OptionKey LoadExceptionObjectInVM = new OptionKey<>(false); @Option(help = "Enable profiling of allocation sites.", type = OptionType.Debug) - public static final OptionValue ProfileAllocations = new OptionValue<>(false); + public static final OptionKey ProfileAllocations = new OptionKey<>(false); @Option(help = "Control the naming of the counters when using ProfileAllocations.", type = OptionType.Debug) - public static final EnumOptionValue ProfileAllocationsContext = new EnumOptionValue<>(ProfileContext.AllocatingMethod); + public static final EnumOptionKey ProfileAllocationsContext = new EnumOptionKey<>(ProfileContext.AllocatingMethod); @Option(help = "Enable profiling of monitor operations.", type = OptionType.Debug) - public static final OptionValue ProfileMonitors = new OptionValue<>(false); + public static final OptionKey ProfileMonitors = new OptionKey<>(false); + + @Option(help = "Handle simple cases for inflated monitors in the fast-path.", type = OptionType.Expert) + public static final OptionKey SimpleFastInflatedLocking = new OptionKey<>(true); @Option(help = "Trace monitor operations on objects whose type contains this substring.", type = OptionType.Debug) - public static final OptionValue TraceMonitorsTypeFilter = new OptionValue<>(null); + public static final OptionKey TraceMonitorsTypeFilter = new OptionKey<>(null); @Option(help = "Trace monitor operations in methods whose fully qualified name contains this substring.", type = OptionType.Debug) - public static final OptionValue TraceMonitorsMethodFilter = new OptionValue<>(null); + public static final OptionKey TraceMonitorsMethodFilter = new OptionKey<>(null); @Option(help = "Emit extra code to dynamically check monitor operations are balanced.", type = OptionType.Debug) - public static final OptionValue VerifyBalancedMonitors = new OptionValue<>(false); + public static final OptionKey VerifyBalancedMonitors = new OptionKey<>(false); //@formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java index 647b8d0c7c5..c96dc5c3654 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java @@ -22,9 +22,10 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.graph.Node; @@ -34,9 +35,9 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConvertNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -50,13 +51,13 @@ import jdk.vm.ci.meta.ResolvedJavaType; * Read {@code Klass::_java_mirror} and incorporate non-null type information into stamp. This is * also used by {@link ClassGetHubNode} to eliminate chains of {@code klass._java_mirror._klass}. */ -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class HubGetClassNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { +@NodeInfo(cycles = CYCLES_1, size = SIZE_1) +public final class HubGetClassNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode { public static final NodeClass TYPE = NodeClass.create(HubGetClassNode.class); @Input protected ValueNode hub; public HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { - super(TYPE, StampFactory.objectNonNull(TypeReference.createWithoutAssumptions(metaAccess.lookupJavaType(Class.class))), null); + super(TYPE, StampFactory.objectNonNull(TypeReference.createWithoutAssumptions(metaAccess.lookupJavaType(Class.class)))); this.hub = hub; } @@ -70,7 +71,7 @@ public final class HubGetClassNode extends FloatingGuardedNode implements Lowera return null; } else { MetaAccessProvider metaAccess = tool.getMetaAccess(); - if (metaAccess != null && hub.isConstant()) { + if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(graph().getOptions())) { ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant()); if (exactType != null) { return ConstantNode.forConstant(tool.getConstantReflection().asJavaClass(exactType), metaAccess); @@ -114,11 +115,16 @@ public final class HubGetClassNode extends FloatingGuardedNode implements Lowera } } + /** + * Any concrete Klass* has a corresponding {@link java.lang.Class}. + */ @Override public boolean isLossless() { - /* - * Any concrete Klass* has a corresponding java.lang.Class - */ + return true; + } + + @Override + public boolean mayNullCheckSkipConversion() { return true; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java index 9c1da836f4a..2577987d090 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; @@ -40,6 +39,7 @@ import org.graalvm.compiler.nodes.ValueNode; 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.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.JavaConstant; @@ -67,7 +67,7 @@ public class IdentityHashCodeNode extends FixedWithNextNode implements Canonical if (object.isConstant()) { assert object.stamp() instanceof AbstractObjectStamp; JavaConstant c = (JavaConstant) object.asConstant(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(getOptions())) { return this; } JavaConstant identityHashCode = null; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java index 177b159f9ec..564dbe65c04 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PRIMARY_SUPERS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.SECONDARY_SUPER_CACHE_LOCATION; @@ -31,34 +33,27 @@ import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.T import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkSecondarySubType; import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkUnknownSubType; import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.createHints; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.displayHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.displayMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.exactHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.exactMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.hintsHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.hintsMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.isNull; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; +import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; +import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Counters; import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Hints; -import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.TypeCheckHints; import org.graalvm.compiler.nodes.ValueNode; @@ -68,7 +63,9 @@ import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode; import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.InstanceOfSnippetsTemplates; +import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; @@ -99,9 +96,9 @@ public class InstanceOfSnippets implements Snippets { */ @Snippet public static Object instanceofWithProfile(Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, - @ConstantParameter boolean nullSeen) { + @ConstantParameter boolean nullSeen, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); if (!nullSeen) { // See comment below for other deoptimization path; the // same reasoning applies here. @@ -117,10 +114,10 @@ public class InstanceOfSnippets implements Snippets { KlassPointer hintHub = hints[i]; boolean positive = hintIsPositive[i]; if (probability(LIKELY_PROBABILITY, hintHub.equal(objectHub))) { - hintsHit.inc(); + counters.hintsHit.inc(); return positive ? trueValue : falseValue; } - hintsMiss.inc(); + counters.hintsMiss.inc(); } // This maybe just be a rare event but it might also indicate a phase change // in the application. Ideally we want to use DeoptimizationAction.None for @@ -134,59 +131,48 @@ public class InstanceOfSnippets implements Snippets { * A test against a final type. */ @Snippet - public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue) { + public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) { - exactMiss.inc(); + counters.exactMiss.inc(); return falseValue; } - exactHit.inc(); + counters.exactHit.inc(); return trueValue; } - @Snippet - public static Object instanceofExactPIC(Object object, KlassPointer exactHub, Object trueValue, Object falseValue) { - KlassPointer exactHubPIC = ResolveConstantSnippets.resolveKlassConstant(exactHub); - return instanceofExact(object, exactHubPIC, trueValue, falseValue); - } - /** * A test against a primary type. */ @Snippet - public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue) { + public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(NOT_LIKELY_PROBABILITY, objectHub.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub))) { - displayMiss.inc(); + counters.displayMiss.inc(); return falseValue; } - displayHit.inc(); + counters.displayHit.inc(); return trueValue; } - @Snippet - public static Object instanceofPrimaryPIC(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue) { - KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return instanceofPrimary(resolvedHub, object, superCheckOffset, trueValue, falseValue); - } - /** * A test against a restricted secondary type type. */ @Snippet - public static Object instanceofSecondary(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue) { + public static Object instanceofSecondary(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, + @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); @@ -197,31 +183,24 @@ public class InstanceOfSnippets implements Snippets { KlassPointer hintHub = hints[i]; boolean positive = hintIsPositive[i]; if (probability(NOT_FREQUENT_PROBABILITY, hintHub.equal(objectHub))) { - hintsHit.inc(); + counters.hintsHit.inc(); return positive ? trueValue : falseValue; } } - hintsMiss.inc(); - if (!checkSecondarySubType(hub, objectHub)) { + counters.hintsMiss.inc(); + if (!checkSecondarySubType(hub, objectHub, counters)) { return falseValue; } return trueValue; } - @Snippet - public static Object instanceofSecondaryPIC(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, - Object falseValue) { - KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return instanceofSecondary(resolvedHub, object, hints, hintIsPositive, trueValue, falseValue); - } - /** * Type test used when the type being tested against is not known at compile time. */ @Snippet - public static Object instanceofDynamic(KlassPointer hub, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean allowNull) { + public static Object instanceofDynamic(KlassPointer hub, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean allowNull, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); if (allowNull) { return trueValue; } else { @@ -229,47 +208,60 @@ public class InstanceOfSnippets implements Snippets { } } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); + KlassPointer nonNullObjectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); // The hub of a primitive type can be null => always return false in this case. - if (hub.isNull() || !checkUnknownSubType(hub, objectHub)) { - return falseValue; + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !hub.isNull())) { + if (checkUnknownSubType(hub, nonNullObjectHub, counters)) { + return trueValue; + } } - return trueValue; + return falseValue; } @Snippet - public static Object isAssignableFrom(Class thisClass, Class otherClass, Object trueValue, Object falseValue) { - if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, otherClass == null)) { + public static Object isAssignableFrom(@NonNullParameter Class thisClassNonNull, Class otherClass, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { + if (otherClass == null) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); return false; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode); - KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode); - if (thisHub.isNull() || otherHub.isNull()) { - // primitive types, only true if equal. - return thisClass == otherClass ? trueValue : falseValue; + Class otherClassNonNull = PiNode.piCastNonNullClass(otherClass, anchorNode); + + if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, thisClassNonNull == otherClassNonNull)) { + return trueValue; } - if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) { - return falseValue; + + KlassPointer thisHub = ClassGetHubNode.readClass(thisClassNonNull); + KlassPointer otherHub = ClassGetHubNode.readClass(otherClassNonNull); + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !thisHub.isNull())) { + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !otherHub.isNull())) { + GuardingNode guardNonNull = SnippetAnchorNode.anchor(); + KlassPointer nonNullOtherHub = ClassGetHubNode.piCastNonNull(otherHub, guardNonNull); + if (TypeCheckSnippetUtils.checkUnknownSubType(thisHub, nonNullOtherHub, counters)) { + return trueValue; + } + } } - return trueValue; + + // If either hub is null, one of them is a primitive type and given that the class is not + // equal, return false. + return falseValue; } public static class Templates extends InstanceOfSnippetsTemplates { private final SnippetInfo instanceofWithProfile = snippet(InstanceOfSnippets.class, "instanceofWithProfile"); private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact"); - private final SnippetInfo instanceofExactPIC = snippet(InstanceOfSnippets.class, "instanceofExactPIC"); private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary"); - private final SnippetInfo instanceofPrimaryPIC = snippet(InstanceOfSnippets.class, "instanceofPrimaryPIC"); private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary", SECONDARY_SUPER_CACHE_LOCATION); - private final SnippetInfo instanceofSecondaryPIC = snippet(InstanceOfSnippets.class, "instanceofSecondaryPIC", SECONDARY_SUPER_CACHE_LOCATION); private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic", SECONDARY_SUPER_CACHE_LOCATION); private final SnippetInfo isAssignableFrom = snippet(InstanceOfSnippets.class, "isAssignableFrom", SECONDARY_SUPER_CACHE_LOCATION); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + private final Counters counters; + + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); + this.counters = new Counters(factory); } @Override @@ -279,13 +271,15 @@ public class InstanceOfSnippets implements Snippets { ValueNode object = instanceOf.getValue(); Assumptions assumptions = instanceOf.graph().getAssumptions(); + OptionValues localOptions = instanceOf.getOptions(); JavaTypeProfile profile = instanceOf.profile(); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(localOptions)) { // FIXME: We can't embed constants in hints. We can't really load them from GOT // either. Hard problem. profile = null; } - TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), profile, assumptions, TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue()); + TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), profile, assumptions, TypeCheckMinProfileHitProbability.getValue(localOptions), + TypeCheckMaxHints.getValue(localOptions)); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type().getType(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), instanceOf.graph()); @@ -299,20 +293,17 @@ public class InstanceOfSnippets implements Snippets { args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs); args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(JavaKind.Boolean), hints.isPositive); } else if (hintInfo.exact != null) { - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofExactPIC : instanceofExact; - args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + args = new Arguments(instanceofExact, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", object); args.add("exactHub", ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) hintInfo.exact).klass(), providers.getMetaAccess(), graph)); } else if (type.isPrimaryType()) { - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofPrimaryPIC : instanceofPrimary; - args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + args = new Arguments(instanceofPrimary, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); args.addConst("superCheckOffset", type.superCheckOffset()); } else { Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph); - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofSecondaryPIC : instanceofSecondary; - args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + args = new Arguments(instanceofSecondary, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs); @@ -323,6 +314,7 @@ public class InstanceOfSnippets implements Snippets { if (hintInfo.hintHitProbability >= 1.0 && hintInfo.exact == null) { args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE); } + args.addConst("counters", counters); return args; } else if (replacer.instanceOf instanceof InstanceOfDynamicNode) { InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; @@ -334,14 +326,17 @@ public class InstanceOfSnippets implements Snippets { args.add("trueValue", replacer.trueValue); args.add("falseValue", replacer.falseValue); args.addConst("allowNull", instanceOf.allowsNull()); + args.addConst("counters", counters); return args; } else if (replacer.instanceOf instanceof ClassIsAssignableFromNode) { ClassIsAssignableFromNode isAssignable = (ClassIsAssignableFromNode) replacer.instanceOf; Arguments args = new Arguments(isAssignableFrom, isAssignable.graph().getGuardsStage(), tool.getLoweringStage()); - args.add("thisClass", isAssignable.getThisClass()); + assert ((ObjectStamp) isAssignable.getThisClass().stamp()).nonNull(); + args.add("thisClassNonNull", isAssignable.getThisClass()); args.add("otherClass", isAssignable.getOtherClass()); args.add("trueValue", replacer.trueValue); args.add("falseValue", replacer.falseValue); + args.addConst("counters", counters); return args; } else { throw GraalError.shouldNotReachHere(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java index 346c94ff104..7cbcd3887f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java @@ -22,9 +22,12 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -35,10 +38,10 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -51,21 +54,29 @@ import jdk.vm.ci.meta.ResolvedJavaType; * Read {@code Klass::_layout_helper} and incorporate any useful stamp information based on any type * information in {@code klass}. */ -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class KlassLayoutHelperNode extends FloatingGuardedNode implements Canonicalizable, Lowerable { +@NodeInfo(cycles = CYCLES_1, size = SIZE_1) +public final class KlassLayoutHelperNode extends FloatingNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(KlassLayoutHelperNode.class); @Input protected ValueNode klass; protected final GraalHotSpotVMConfig config; public KlassLayoutHelperNode(@InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { - this(config, klass, null); + super(TYPE, StampFactory.forKind(JavaKind.Int)); + this.config = config; + this.klass = klass; } - public KlassLayoutHelperNode(@InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass, ValueNode guard) { - super(TYPE, StampFactory.forKind(JavaKind.Int), (GuardingNode) guard); - this.klass = klass; - this.config = config; + public static ValueNode create(GraalHotSpotVMConfig config, ValueNode klass, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess) { + Stamp stamp = StampFactory.forKind(JavaKind.Int); + return canonical(null, config, klass, stamp, constantReflection, metaAccess); + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { + ValueNode valueNode = create(config, klass, b.getConstantReflection(), b.getMetaAccess()); + b.push(JavaKind.Int, b.append(valueNode)); + return true; } @Override @@ -97,29 +108,38 @@ public final class KlassLayoutHelperNode extends FloatingGuardedNode implements if (tool.allUsagesAvailable() && hasNoUsages()) { return null; } else { - if (klass.isConstant()) { - if (!klass.asConstant().isDefaultForKind()) { - Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset); - return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); - } - } - if (klass instanceof LoadHubNode) { - LoadHubNode hub = (LoadHubNode) klass; - Stamp hubStamp = hub.getValue().stamp(); - if (hubStamp instanceof ObjectStamp) { - ObjectStamp ostamp = (ObjectStamp) hubStamp; - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); - if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) { - // The layout for all object arrays is the same. - Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset); - return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); - } - } - } - return this; + return canonical(this, config, klass, stamp(), tool.getConstantReflection(), tool.getMetaAccess()); } } + private static ValueNode canonical(KlassLayoutHelperNode klassLayoutHelperNode, GraalHotSpotVMConfig config, ValueNode klass, Stamp stamp, ConstantReflectionProvider constantReflection, + MetaAccessProvider metaAccess) { + KlassLayoutHelperNode self = klassLayoutHelperNode; + if (klass.isConstant()) { + if (!klass.asConstant().isDefaultForKind()) { + Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp, constant, metaAccess); + } + } + if (klass instanceof LoadHubNode) { + LoadHubNode hub = (LoadHubNode) klass; + Stamp hubStamp = hub.getValue().stamp(); + if (hubStamp instanceof ObjectStamp) { + ObjectStamp ostamp = (ObjectStamp) hubStamp; + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); + if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) { + // The layout for all object arrays is the same. + Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp, constant, metaAccess); + } + } + } + if (self == null) { + self = new KlassLayoutHelperNode(config, klass); + } + return self; + } + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java index 02eaf651a88..ebb55b42d4b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java @@ -29,28 +29,33 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeExceptionOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeExceptionPc; -import static org.graalvm.compiler.nodes.PiNode.piCast; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.LoadExceptionObjectInVM; +import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; +import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.ReadRegisterNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Snippet for loading the exception object at the start of an exception dispatcher. @@ -63,32 +68,31 @@ import jdk.vm.ci.code.TargetDescription; */ public class LoadExceptionObjectSnippets implements Snippets { - /** - * Alternative way to implement exception object loading. - */ - private static final boolean USE_C_RUNTIME = HotspotSnippetsOptions.LoadExceptionObjectInVM.getValue(); - @Snippet public static Object loadException(@ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); Object exception = readExceptionOop(thread); writeExceptionOop(thread, null); - writeExceptionPc(thread, Word.zero()); - return piCast(exception, StampFactory.forNodeIntrinsic()); + writeExceptionPc(thread, WordFactory.zero()); + return piCastToSnippetReplaceeStamp(exception); } public static class Templates extends AbstractTemplates { private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION); + private final HotSpotWordTypes wordTypes; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); + this.wordTypes = providers.getWordTypes(); } public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) { - if (USE_C_RUNTIME) { - StructuredGraph graph = loadExceptionObject.graph(); - ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false)); + StructuredGraph graph = loadExceptionObject.graph(); + if (LoadExceptionObjectInVM.getValue(graph.getOptions())) { + ResolvedJavaType wordType = providers.getMetaAccess().lookupJavaType(Word.class); + Stamp stamp = wordTypes.getWordStamp(wordType); + ReadRegisterNode thread = graph.add(new ReadRegisterNode(stamp, registers.getThreadRegister(), true, false)); graph.addBeforeFixed(loadExceptionObject, thread); ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread)); loadExceptionC.setStateAfter(loadExceptionObject.stateAfter()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java index 91747913671..c90e9694a1e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java @@ -22,14 +22,18 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode.beginLockScope; -import static org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode.compareAndSwap; import static org.graalvm.compiler.hotspot.nodes.EndLockScopeNode.endLockScope; import static org.graalvm.compiler.hotspot.nodes.VMErrorNode.vmError; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_CXQ_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace; @@ -39,6 +43,11 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadWordFromObject; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockDisplacedMarkOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.markOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.monitorMask; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorCxqOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorEntryListOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorOwnerOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorRecursionsOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; @@ -47,12 +56,16 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileMonitors; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.SimpleFastInflatedLocking; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TraceMonitorsMethodFilter; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TraceMonitorsTypeFilter; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.VerifyBalancedMonitors; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; @@ -63,7 +76,6 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -71,11 +83,11 @@ import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.nodes.AcquiredCASLockNode; import org.graalvm.compiler.hotspot.nodes.CurrentLockNode; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.FastAcquireBiasedLockNode; import org.graalvm.compiler.hotspot.nodes.MonitorCounterNode; import org.graalvm.compiler.hotspot.word.KlassPointer; @@ -90,14 +102,14 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorExitNode; import org.graalvm.compiler.nodes.java.RawMonitorEnterNode; -import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.replacements.Log; import org.graalvm.compiler.replacements.SnippetCounter; @@ -106,7 +118,10 @@ import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.word.Word; -import org.graalvm.compiler.word.WordBase; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordBase; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.Register; @@ -114,7 +129,6 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -201,13 +215,13 @@ public class MonitorSnippets implements Snippets { private static final boolean PROFILE_CONTEXT = false; @Fold - static boolean doProfile() { - return ProfileMonitors.getValue(); + static boolean doProfile(OptionValues options) { + return ProfileMonitors.getValue(options); } @Snippet public static void monitorenter(Object object, KlassPointer hub, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister, - @ConstantParameter boolean trace) { + @ConstantParameter boolean trace, @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { verifyOop(object); // Load the mark word - this includes a null-check on object @@ -215,197 +229,256 @@ public class MonitorSnippets implements Snippets { final Word lock = beginLockScope(lockDepth); - trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object)); + Pointer objectPointer = Word.objectToTrackedPointer(object); + trace(trace, " object: 0x%016lx\n", objectPointer); trace(trace, " lock: 0x%016lx\n", lock); trace(trace, " mark: 0x%016lx\n", mark); - incCounter(); + incCounter(options); if (useBiasedLocking(INJECTED_VMCONFIG)) { - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid. - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits. - final Word biasableLockBits = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); - - // Check whether the bias pattern is present in the object's mark word - // and the bias owner and the epoch are both still current. - final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); - final Word thread = registerAsWord(threadRegister); - final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace(INJECTED_VMCONFIG)); - trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); - trace(trace, " thread: 0x%016lx\n", thread); - trace(trace, " tmp: 0x%016lx\n", tmp); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, tmp.equal(0))) { - // Object is already biased to current thread -> done - traceObject(trace, "+lock{bias:existing}", object, true); - lockBiasExisting.inc(); - FastAcquireBiasedLockNode.mark(object); + if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, options, counters)) { return; } - - // Now check to see whether biasing is enabled for this object - if (probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { - // Biasing not enabled -> fall through to lightweight locking - unbiasable.inc(); - } else { - // At this point we know that the mark word has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the mark word in order to - // know what operations can be legally performed on the object's - // mark word. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biasable and we have to revoke - // the bias on this object. - if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { - // Biasing is still enabled for object's type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype mark word. (Note that the prototype mark word's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - Word unbiasedMark = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG) | ageMaskInPlace(INJECTED_VMCONFIG) | epochMaskInPlace(INJECTED_VMCONFIG)); - Word biasedMark = unbiasedMark.or(thread); - trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (probability(VERY_FAST_PATH_PROBABILITY, - compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) { - // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:acquired}", object, true); - lockBiasAcquired.inc(); - return; - } - // If the biasing toward our thread failed, this means that another thread - // owns the bias and we need to revoke that bias. The revocation will occur - // in the interpreter runtime. - traceObject(trace, "+lock{stub:revoke}", object, true); - lockStubRevoke.inc(); - } else { - // At this point we know the epoch has expired, meaning that the - // current bias owner, if any, is actually invalid. Under these - // circumstances _only_, are we allowed to use the current mark word - // value as the comparison value when doing the CAS to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - Word biasedMark = prototypeMarkWord.or(thread); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (probability(VERY_FAST_PATH_PROBABILITY, - compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) { - // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:transfer}", object, true); - lockBiasTransfer.inc(); - return; - } - // If the biasing toward our thread failed, then another thread - // succeeded in biasing it toward itself and we need to revoke that - // bias. The revocation will occur in the runtime in the slow case. - traceObject(trace, "+lock{stub:epoch-expired}", object, true); - lockStubEpochExpired.inc(); - } - monitorenterStubC(MONITORENTER, object, lock); - return; - } else { - // The prototype mark word doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - Word result = compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), mark, prototypeMarkWord, MARK_WORD_LOCATION); - - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - - if (ENABLE_BREAKPOINT) { - bkpt(object, mark, tmp, result); - } - revokeBias.inc(); - } - } + // not biased, fall-through } - - // Create the unlocked mark word pattern - Word unlockedMark = mark.or(unlockedMask(INJECTED_VMCONFIG)); - trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); - - // Copy this unlocked mark word into the lock slot on the stack - lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), unlockedMark, DISPLACED_MARK_WORD_LOCATION); - - // Test if the object's mark word is unlocked, and if so, store the - // (address of) the lock slot into the object's mark word. - Word currentMark = compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), unlockedMark, lock, MARK_WORD_LOCATION); - if (probability(BranchProbabilityNode.SLOW_PATH_PROBABILITY, currentMark.notEqual(unlockedMark))) { - trace(trace, " currentMark: 0x%016lx\n", currentMark); - // The mark word in the object header was not the same. - // Either the object is locked by another thread or is already locked - // by the current thread. The latter is true if the mark word - // is a stack pointer into the current thread's stack, i.e.: - // - // 1) (currentMark & aligned_mask) == 0 - // 2) rsp <= currentMark - // 3) currentMark <= rsp + page_size - // - // These 3 tests can be done by evaluating the following expression: - // - // (currentMark - rsp) & (aligned_mask - page_size) - // - // assuming both the stack pointer and page_size have their least - // significant 2 bits cleared and page_size is a power of 2 - final Word alignedMask = Word.unsigned(wordSize() - 1); - final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias); - if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) { - // Most likely not a recursive lock, go into a slow runtime call - traceObject(trace, "+lock{stub:failed-cas}", object, true); - lockStubFailedCas.inc(); - monitorenterStubC(MONITORENTER, object, lock); + if (inlineFastLockSupported(options) && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) { + // Inflated case + if (tryEnterInflated(object, lock, mark, threadRegister, trace, options, counters)) { return; - } else { - // Recursively locked => write 0 to the lock slot - lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), Word.zero(), DISPLACED_MARK_WORD_LOCATION); - traceObject(trace, "+lock{cas:recursive}", object, true); - lockCasRecursive.inc(); } } else { - traceObject(trace, "+lock{cas}", object, true); - lockCas.inc(); - AcquiredCASLockNode.mark(object); + // Create the unlocked mark word pattern + Word unlockedMark = mark.or(unlockedMask(INJECTED_VMCONFIG)); + trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); + + // Copy this unlocked mark word into the lock slot on the stack + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), unlockedMark, DISPLACED_MARK_WORD_LOCATION); + + // make sure previous store does not float below compareAndSwap + MembarNode.memoryBarrier(STORE_STORE); + + // Test if the object's mark word is unlocked, and if so, store the + // (address of) the lock slot into the object's mark word. + Word currentMark = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), unlockedMark, lock, MARK_WORD_LOCATION); + if (probability(FAST_PATH_PROBABILITY, currentMark.equal(unlockedMark))) { + traceObject(trace, "+lock{cas}", object, true, options); + counters.lockCas.inc(); + AcquiredCASLockNode.mark(object); + return; + } else { + trace(trace, " currentMark: 0x%016lx\n", currentMark); + // The mark word in the object header was not the same. + // Either the object is locked by another thread or is already locked + // by the current thread. The latter is true if the mark word + // is a stack pointer into the current thread's stack, i.e.: + // + // 1) (currentMark & aligned_mask) == 0 + // 2) rsp <= currentMark + // 3) currentMark <= rsp + page_size + // + // These 3 tests can be done by evaluating the following expression: + // + // (currentMark - rsp) & (aligned_mask - page_size) + // + // assuming both the stack pointer and page_size have their least + // significant 2 bits cleared and page_size is a power of 2 + final Word alignedMask = WordFactory.unsigned(wordSize() - 1); + final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias); + if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).equal(0))) { + // Recursively locked => write 0 to the lock slot + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), WordFactory.zero(), DISPLACED_MARK_WORD_LOCATION); + traceObject(trace, "+lock{cas:recursive}", object, true, options); + counters.lockCasRecursive.inc(); + return; + } + traceObject(trace, "+lock{stub:failed-cas/stack}", object, true, options); + counters.lockStubFailedCas.inc(); + } } + // slow-path runtime-call + monitorenterStubC(MONITORENTER, object, lock); + } + + private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid. + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits. + final Word biasableLockBits = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); + + // Check whether the bias pattern is present in the object's mark word + // and the bias owner and the epoch are both still current. + final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); + final Word thread = registerAsWord(threadRegister); + final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace(INJECTED_VMCONFIG)); + trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); + trace(trace, " thread: 0x%016lx\n", thread); + trace(trace, " tmp: 0x%016lx\n", tmp); + if (probability(FAST_PATH_PROBABILITY, tmp.equal(0))) { + // Object is already biased to current thread -> done + traceObject(trace, "+lock{bias:existing}", object, true, options); + counters.lockBiasExisting.inc(); + FastAcquireBiasedLockNode.mark(object); + return true; + } + + // Now check to see whether biasing is enabled for this object + if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.equal(WordFactory.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { + Pointer objectPointer = Word.objectToTrackedPointer(object); + // At this point we know that the mark word has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the mark word in order to + // know what operations can be legally performed on the object's + // mark word. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biasable and we have to revoke + // the bias on this object. + if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { + // Biasing is still enabled for object's type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype mark word. (Note that the prototype mark word's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + Word unbiasedMark = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG) | ageMaskInPlace(INJECTED_VMCONFIG) | epochMaskInPlace(INJECTED_VMCONFIG)); + Word biasedMark = unbiasedMark.or(thread); + trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), unbiasedMark, biasedMark, MARK_WORD_LOCATION))) { + // Object is now biased to current thread -> done + traceObject(trace, "+lock{bias:acquired}", object, true, options); + counters.lockBiasAcquired.inc(); + return true; + } + // If the biasing toward our thread failed, this means that another thread + // owns the bias and we need to revoke that bias. The revocation will occur + // in the interpreter runtime. + traceObject(trace, "+lock{stub:revoke}", object, true, options); + counters.lockStubRevoke.inc(); + } else { + // At this point we know the epoch has expired, meaning that the + // current bias owner, if any, is actually invalid. Under these + // circumstances _only_, are we allowed to use the current mark word + // value as the comparison value when doing the CAS to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + Word biasedMark = prototypeMarkWord.or(thread); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, biasedMark, MARK_WORD_LOCATION))) { + // Object is now biased to current thread -> done + traceObject(trace, "+lock{bias:transfer}", object, true, options); + counters.lockBiasTransfer.inc(); + return true; + } + // If the biasing toward our thread failed, then another thread + // succeeded in biasing it toward itself and we need to revoke that + // bias. The revocation will occur in the runtime in the slow case. + traceObject(trace, "+lock{stub:epoch-expired}", object, true, options); + counters.lockStubEpochExpired.inc(); + } + // slow-path runtime-call + monitorenterStubC(MONITORENTER, object, lock); + return true; + } else { + // The prototype mark word doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + Word result = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, prototypeMarkWord, MARK_WORD_LOCATION); + + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + + if (ENABLE_BREAKPOINT) { + bkpt(object, mark, tmp, result); + } + counters.revokeBias.inc(); + return false; + } + } else { + // Biasing not enabled -> fall through to lightweight locking + counters.unbiasable.inc(); + return false; + } + } + + @Fold + public static boolean useFastInflatedLocking(OptionValues options) { + return SimpleFastInflatedLocking.getValue(options); + } + + private static boolean inlineFastLockSupported(OptionValues options) { + return inlineFastLockSupported(INJECTED_VMCONFIG, options); + } + + private static boolean inlineFastLockSupported(GraalHotSpotVMConfig config, OptionValues options) { + return useFastInflatedLocking(options) && monitorMask(config) >= 0 && objectMonitorOwnerOffset(config) >= 0; + } + + private static boolean tryEnterInflated(Object object, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + // write non-zero value to lock slot + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), lock, DISPLACED_MARK_WORD_LOCATION); + // mark is a pointer to the ObjectMonitor + monitorMask + Word monitor = mark.subtract(monitorMask(INJECTED_VMCONFIG)); + int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); + Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION); + if (probability(FREQUENT_PROBABILITY, owner.equal(0))) { + // it appears unlocked (owner == 0) + if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, registerAsWord(threadRegister), OBJECT_MONITOR_OWNER_LOCATION))) { + // success + traceObject(trace, "+lock{inflated:cas}", object, true, options); + counters.inflatedCas.inc(); + return true; + } else { + traceObject(trace, "+lock{stub:inflated:failed-cas}", object, true, options); + counters.inflatedFailedCas.inc(); + } + } else { + traceObject(trace, "+lock{stub:inflated:owned}", object, true, options); + counters.inflatedOwned.inc(); + } + return false; } /** * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) { verifyOop(object); - incCounter(); + incCounter(options); if (object == null) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); } // BeginLockScope nodes do not read from object so a use of object // cannot float about the null check above final Word lock = beginLockScope(lockDepth); - traceObject(trace, "+lock{stub}", object, true); + traceObject(trace, "+lock{stub}", object, true, options); monitorenterStubC(MONITORENTER, object, lock); } @Snippet - public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object)); + final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); if (useBiasedLocking(INJECTED_VMCONFIG)) { // Check for biased locking unlock case, which is a no-op // Note: we do not have to check the thread ID for two reasons. @@ -413,13 +486,12 @@ public class MonitorSnippets implements Snippets { // a higher level. Second, if the bias was revoked while we held the // lock, the object could not be rebiased toward another thread, so // the bias bit would be clear. - final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); trace(trace, " mark: 0x%016lx\n", mark); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { + if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(WordFactory.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { endLockScope(); - decCounter(); - traceObject(trace, "-lock{bias}", object, false); - unlockBias.inc(); + decCounter(options); + traceObject(trace, "-lock{bias}", object, false, options); + counters.unlockBias.inc(); return; } } @@ -430,46 +502,95 @@ public class MonitorSnippets implements Snippets { final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), DISPLACED_MARK_WORD_LOCATION); trace(trace, " displacedMark: 0x%016lx\n", displacedMark); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { + if (probability(NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { // Recursive locking => done - traceObject(trace, "-lock{recursive}", object, false); - unlockCasRecursive.inc(); + traceObject(trace, "-lock{recursive}", object, false, options); + counters.unlockCasRecursive.inc(); } else { - verifyOop(object); - // Test if object's mark word is pointing to the displaced mark word, and if so, restore - // the displaced mark in the object - if the object's mark word is not pointing to - // the displaced mark word, do unlocking via runtime call. - if (probability(VERY_SLOW_PATH_PROBABILITY, - DirectCompareAndSwapNode.compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock))) { - // The object's mark word was not pointing to the displaced header, - // we do unlocking via runtime call. - traceObject(trace, "-lock{stub}", object, false); - unlockStub.inc(); - monitorexitStubC(MONITOREXIT, object, lock); - } else { - traceObject(trace, "-lock{cas}", object, false); - unlockCas.inc(); + if (!tryExitInflated(object, mark, lock, threadRegister, trace, options, counters)) { + verifyOop(object); + // Test if object's mark word is pointing to the displaced mark word, and if so, + // restore + // the displaced mark in the object - if the object's mark word is not pointing to + // the displaced mark word, do unlocking via runtime call. + Pointer objectPointer = Word.objectToTrackedPointer(object); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), lock, displacedMark, MARK_WORD_LOCATION))) { + traceObject(trace, "-lock{cas}", object, false, options); + counters.unlockCas.inc(); + } else { + // The object's mark word was not pointing to the displaced header + traceObject(trace, "-lock{stub}", object, false, options); + counters.unlockStub.inc(); + monitorexitStubC(MONITOREXIT, object, lock); + } } } endLockScope(); - decCounter(); + decCounter(options); + } + + private static boolean inlineFastUnlockSupported(OptionValues options) { + return inlineFastUnlockSupported(INJECTED_VMCONFIG, options); + } + + private static boolean inlineFastUnlockSupported(GraalHotSpotVMConfig config, OptionValues options) { + return useFastInflatedLocking(options) && objectMonitorEntryListOffset(config) >= 0 && objectMonitorCxqOffset(config) >= 0 && monitorMask(config) >= 0 && + objectMonitorOwnerOffset(config) >= 0 && objectMonitorRecursionsOffset(config) >= 0; + } + + private static boolean tryExitInflated(Object object, Word mark, Word lock, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + if (!inlineFastUnlockSupported(options)) { + return false; + } + if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) { + // Inflated case + // mark is a pointer to the ObjectMonitor + monitorMask + Word monitor = mark.subtract(monitorMask(INJECTED_VMCONFIG)); + int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); + Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION); + int recursionsOffset = objectMonitorRecursionsOffset(INJECTED_VMCONFIG); + Word recursions = monitor.readWord(recursionsOffset, OBJECT_MONITOR_RECURSION_LOCATION); + Word thread = registerAsWord(threadRegister); + if (probability(FAST_PATH_PROBABILITY, owner.xor(thread).or(recursions).equal(0))) { + // owner == thread && recursions == 0 + int cxqOffset = objectMonitorCxqOffset(INJECTED_VMCONFIG); + Word cxq = monitor.readWord(cxqOffset, OBJECT_MONITOR_CXQ_LOCATION); + int entryListOffset = objectMonitorEntryListOffset(INJECTED_VMCONFIG); + Word entryList = monitor.readWord(entryListOffset, OBJECT_MONITOR_ENTRY_LIST_LOCATION); + if (probability(FREQUENT_PROBABILITY, cxq.or(entryList).equal(0))) { + // cxq == 0 && entryList == 0 + // Nobody is waiting, success + // release_store + MembarNode.memoryBarrier(LOAD_STORE | STORE_STORE); + monitor.writeWord(ownerOffset, WordFactory.zero()); + traceObject(trace, "-lock{inflated:simple}", object, false, options); + counters.unlockInflatedSimple.inc(); + return true; + } + } + counters.unlockStubInflated.inc(); + traceObject(trace, "-lock{stub:inflated}", object, false, options); + monitorexitStubC(MONITOREXIT, object, lock); + return true; + } + return false; } /** * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) { verifyOop(object); - traceObject(trace, "-lock{stub}", object, false); + traceObject(trace, "-lock{stub}", object, false, options); final Word lock = CurrentLockNode.currentLock(lockDepth); monitorexitStubC(MONITOREXIT, object, lock); endLockScope(); - decCounter(); + decCounter(options); } - public static void traceObject(boolean enabled, String action, Object object, boolean enter) { - if (doProfile()) { + public static void traceObject(boolean enabled, String action, Object object, boolean enter, OptionValues options) { + if (doProfile(options)) { DynamicCounterNode.counter(action, enter ? "number of monitor enters" : "number of monitor exits", 1, PROFILE_CONTEXT); } if (enabled) { @@ -496,18 +617,21 @@ public class MonitorSnippets implements Snippets { @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word mark, Word tmp, Word value); - private static final boolean VERIFY_BALANCED_MONITORS = VerifyBalancedMonitors.getValue(); + @Fold + static boolean verifyBalancedMonitors(OptionValues options) { + return VerifyBalancedMonitors.getValue(options); + } - public static void incCounter() { - if (VERIFY_BALANCED_MONITORS) { + public static void incCounter(OptionValues options) { + if (verifyBalancedMonitors(options)) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION); } } - public static void decCounter() { - if (VERIFY_BALANCED_MONITORS) { + public static void decCounter(OptionValues options) { + if (verifyBalancedMonitors(options)) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION); @@ -529,6 +653,64 @@ public class MonitorSnippets implements Snippets { } } + public static class Counters { + /** + * Counters for the various paths for acquiring a lock. The counters whose names start with + * {@code "lock"} are mutually exclusive. The other counters are for paths that may be + * shared. + */ + public final SnippetCounter lockBiasExisting; + public final SnippetCounter lockBiasAcquired; + public final SnippetCounter lockBiasTransfer; + public final SnippetCounter lockCas; + public final SnippetCounter lockCasRecursive; + public final SnippetCounter lockStubEpochExpired; + public final SnippetCounter lockStubRevoke; + public final SnippetCounter lockStubFailedCas; + public final SnippetCounter inflatedCas; + public final SnippetCounter inflatedFailedCas; + public final SnippetCounter inflatedOwned; + public final SnippetCounter unbiasable; + public final SnippetCounter revokeBias; + + /** + * Counters for the various paths for releasing a lock. The counters whose names start with + * {@code "unlock"} are mutually exclusive. The other counters are for paths that may be + * shared. + */ + public final SnippetCounter unlockBias; + public final SnippetCounter unlockCas; + public final SnippetCounter unlockCasRecursive; + public final SnippetCounter unlockStub; + public final SnippetCounter unlockStubInflated; + public final SnippetCounter unlockInflatedSimple; + + public Counters(SnippetCounter.Group.Factory factory) { + SnippetCounter.Group enter = factory.createSnippetCounterGroup("MonitorEnters"); + SnippetCounter.Group exit = factory.createSnippetCounterGroup("MonitorExits"); + lockBiasExisting = new SnippetCounter(enter, "lock{bias:existing}", "bias-locked previously biased object"); + lockBiasAcquired = new SnippetCounter(enter, "lock{bias:acquired}", "bias-locked newly biased object"); + lockBiasTransfer = new SnippetCounter(enter, "lock{bias:transfer}", "bias-locked, biased transferred"); + lockCas = new SnippetCounter(enter, "lock{cas}", "cas-locked an object"); + lockCasRecursive = new SnippetCounter(enter, "lock{cas:recursive}", "cas-locked, recursive"); + lockStubEpochExpired = new SnippetCounter(enter, "lock{stub:epoch-expired}", "stub-locked, epoch expired"); + lockStubRevoke = new SnippetCounter(enter, "lock{stub:revoke}", "stub-locked, biased revoked"); + lockStubFailedCas = new SnippetCounter(enter, "lock{stub:failed-cas/stack}", "stub-locked, failed cas and stack locking"); + inflatedCas = new SnippetCounter(enter, "lock{inflated:cas}", "heavyweight-locked, cas-locked"); + inflatedFailedCas = new SnippetCounter(enter, "lock{inflated:failed-cas}", "heavyweight-locked, failed cas"); + inflatedOwned = new SnippetCounter(enter, "lock{inflated:owned}", "heavyweight-locked, already owned"); + unbiasable = new SnippetCounter(enter, "unbiasable", "object with unbiasable type"); + revokeBias = new SnippetCounter(enter, "revokeBias", "object had bias revoked"); + + unlockBias = new SnippetCounter(exit, "unlock{bias}", "bias-unlocked an object"); + unlockCas = new SnippetCounter(exit, "unlock{cas}", "cas-unlocked an object"); + unlockCasRecursive = new SnippetCounter(exit, "unlock{cas:recursive}", "cas-unlocked an object, recursive"); + unlockStub = new SnippetCounter(exit, "unlock{stub}", "stub-unlocked an object"); + unlockStubInflated = new SnippetCounter(exit, "unlock{stub:inflated}", "stub-unlocked an object with inflated monitor"); + unlockInflatedSimple = new SnippetCounter(exit, "unlock{inflated}", "unlocked an object monitor"); + } + } + public static class Templates extends AbstractTemplates { private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter"); @@ -539,10 +721,13 @@ public class MonitorSnippets implements Snippets { private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); private final boolean useFastLocking; + public final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, boolean useFastLocking) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, boolean useFastLocking) { + super(options, providers, providers.getSnippetReflection(), target); this.useFastLocking = useFastLocking; + + this.counters = new Counters(factory); } public void lower(RawMonitorEnterNode monitorenterNode, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -559,18 +744,22 @@ public class MonitorSnippets implements Snippets { args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("stackPointerRegister", registers.getStackPointerRegister()); - args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); } else { args = new Arguments(monitorenterStub, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", monitorenterNode.object()); args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth()); - args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); } template(args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args); } - public void lower(MonitorExitNode monitorexitNode, LoweringTool tool) { + public void lower(MonitorExitNode monitorexitNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = monitorexitNode.graph(); Arguments args; @@ -581,14 +770,17 @@ public class MonitorSnippets implements Snippets { } args.add("object", monitorexitNode.object()); args.addConst("lockDepth", monitorexitNode.getMonitorId().getLockDepth()); - args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("threadRegister", registers.getThreadRegister()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args); } public static boolean isTracingEnabledForType(ValueNode object) { ResolvedJavaType type = StampTool.typeOrNull(object.stamp()); - String filter = TraceMonitorsTypeFilter.getValue(); + String filter = TraceMonitorsTypeFilter.getValue(object.getOptions()); if (filter == null) { return false; } else { @@ -602,18 +794,18 @@ public class MonitorSnippets implements Snippets { } } - public static boolean isTracingEnabledForMethod(ResolvedJavaMethod method) { - String filter = TraceMonitorsMethodFilter.getValue(); + public static boolean isTracingEnabledForMethod(StructuredGraph graph) { + String filter = TraceMonitorsMethodFilter.getValue(graph.getOptions()); if (filter == null) { return false; } else { if (filter.length() == 0) { return true; } - if (method == null) { + if (graph.method() == null) { return false; } - return (method.format("%H.%n").contains(filter)); + return (graph.method().format("%H.%n").contains(filter)); } } @@ -622,7 +814,7 @@ public class MonitorSnippets implements Snippets { * return points of the graph to initialize and check the monitor counter respectively. */ private void checkBalancedMonitors(StructuredGraph graph, LoweringTool tool) { - if (VERIFY_BALANCED_MONITORS) { + if (VerifyBalancedMonitors.getValue(options)) { NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. @@ -634,7 +826,7 @@ public class MonitorSnippets implements Snippets { graph.addAfterFixed(graph.start(), invoke); StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null); - InliningUtil.inline(invoke, inlineeGraph, false, null, null); + InliningUtil.inline(invoke, inlineeGraph, false, null); List rets = graph.getNodes(ReturnNode.TYPE).snapshot(); for (ReturnNode ret : rets) { @@ -652,7 +844,7 @@ public class MonitorSnippets implements Snippets { Arguments args = new Arguments(checkCounter, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("errMsg", msg); inlineeGraph = template(args).copySpecializedGraph(); - InliningUtil.inline(invoke, inlineeGraph, false, null, null); + InliningUtil.inline(invoke, inlineeGraph, false, null); } } } @@ -667,31 +859,4 @@ public class MonitorSnippets implements Snippets { @NodeIntrinsic(ForeignCallNode.class) public static native void monitorexitStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); - - /** - * Counters for the various paths for acquiring a lock. The counters whose names start with - * {@code "lock"} are mutually exclusive. The other counters are for paths that may be shared. - */ - public static final SnippetCounter.Group lockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorEnters") : null; - public static final SnippetCounter lockBiasExisting = new SnippetCounter(lockCounters, "lock{bias:existing}", "bias-locked previously biased object"); - public static final SnippetCounter lockBiasAcquired = new SnippetCounter(lockCounters, "lock{bias:acquired}", "bias-locked newly biased object"); - public static final SnippetCounter lockBiasTransfer = new SnippetCounter(lockCounters, "lock{bias:transfer}", "bias-locked, biased transferred"); - public static final SnippetCounter lockCas = new SnippetCounter(lockCounters, "lock{cas}", "cas-locked an object"); - public static final SnippetCounter lockCasRecursive = new SnippetCounter(lockCounters, "lock{cas:recursive}", "cas-locked, recursive"); - public static final SnippetCounter lockStubEpochExpired = new SnippetCounter(lockCounters, "lock{stub:epoch-expired}", "stub-locked, epoch expired"); - public static final SnippetCounter lockStubRevoke = new SnippetCounter(lockCounters, "lock{stub:revoke}", "stub-locked, biased revoked"); - public static final SnippetCounter lockStubFailedCas = new SnippetCounter(lockCounters, "lock{stub:failed-cas}", "stub-locked, failed cas"); - - public static final SnippetCounter unbiasable = new SnippetCounter(lockCounters, "unbiasable", "object with unbiasable type"); - public static final SnippetCounter revokeBias = new SnippetCounter(lockCounters, "revokeBias", "object had bias revoked"); - - /** - * Counters for the various paths for releasing a lock. The counters whose names start with - * {@code "unlock"} are mutually exclusive. The other counters are for paths that may be shared. - */ - public static final SnippetCounter.Group unlockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorExits") : null; - public static final SnippetCounter unlockBias = new SnippetCounter(unlockCounters, "unlock{bias}", "bias-unlocked an object"); - public static final SnippetCounter unlockCas = new SnippetCounter(unlockCounters, "unlock{cas}", "cas-unlocked an object"); - public static final SnippetCounter unlockCasRecursive = new SnippetCounter(unlockCounters, "unlock{cas:recursive}", "cas-unlocked an object, recursive"); - public static final SnippetCounter unlockStub = new SnippetCounter(unlockCounters, "unlock{stub}", "stub-unlocked an object"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java index 564e89a36f1..ea6caf164f0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java @@ -22,8 +22,9 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotMetaAccessProvider.computeArrayAllocationSize; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION; @@ -53,8 +54,10 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop; -import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCast; -import static org.graalvm.compiler.nodes.PiNode.piCast; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocations; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocationsContext; +import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCastToSnippetReplaceeStamp; +import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; @@ -64,14 +67,11 @@ import static org.graalvm.compiler.replacements.ReplacementsUtil.staticAssert; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring; import static org.graalvm.compiler.replacements.nodes.ExplodeLoopNode.explodeLoop; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; -import static jdk.vm.ci.hotspot.HotSpotMetaAccessProvider.computeArrayAllocationSize; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.Debug; @@ -90,13 +90,13 @@ import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; -import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.PrefetchAllocateNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; import org.graalvm.compiler.nodes.debug.VerifyHeapNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; @@ -107,8 +107,10 @@ import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.ReplacementsUtil; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -116,6 +118,8 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; 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.vm.ci.code.CodeUtil; import jdk.vm.ci.code.MemoryBarriers; @@ -133,8 +137,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; */ public class NewObjectSnippets implements Snippets { - public static final LocationIdentity INIT_LOCATION = NamedLocationIdentity.mutable("Initialization"); - enum ProfileContext { AllocatingMethod, InstanceOrArray, @@ -144,8 +146,8 @@ public class NewObjectSnippets implements Snippets { } @Fold - static String createName(String path, String typeContext) { - switch (HotspotSnippetsOptions.ProfileAllocationsContext.getValue()) { + static String createName(String path, String typeContext, OptionValues options) { + switch (ProfileAllocationsContext.getValue(options)) { case AllocatingMethod: return ""; case InstanceOrArray: @@ -161,21 +163,21 @@ public class NewObjectSnippets implements Snippets { } @Fold - static boolean doProfile() { - return HotspotSnippetsOptions.ProfileAllocations.getValue(); + static boolean doProfile(OptionValues options) { + return ProfileAllocations.getValue(options); } @Fold - static boolean withContext() { - ProfileContext context = HotspotSnippetsOptions.ProfileAllocationsContext.getValue(); + static boolean withContext(OptionValues options) { + ProfileContext context = ProfileAllocationsContext.getValue(options); return context == ProfileContext.AllocatingMethod || context == ProfileContext.AllocatedTypesInMethod; } - protected static void profileAllocation(String path, long size, String typeContext) { - if (doProfile()) { - String name = createName(path, typeContext); + protected static void profileAllocation(String path, long size, String typeContext, OptionValues options) { + if (doProfile(options)) { + String name = createName(path, typeContext, options); - boolean context = withContext(); + boolean context = withContext(options); DynamicCounterNode.counter(name, "number of bytes allocated", size, context); DynamicCounterNode.counter(name, "number of allocations", 1, context); } @@ -198,8 +200,14 @@ public class NewObjectSnippets implements Snippets { } @Snippet - public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter boolean constantSize, @ConstantParameter String typeContext) { + public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { + return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters)); + } + + public static Object allocateInstanceHelper(int size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents, + Register threadRegister, boolean constantSize, String typeContext, OptionValues options, Counters counters) { Object result; Word thread = registerAsWord(threadRegister); Word top = readTlabTop(thread); @@ -208,39 +216,53 @@ public class NewObjectSnippets implements Snippets { if (useTLAB(INJECTED_VMCONFIG) && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, false); - result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, true); + result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters); } else { - new_stub.inc(); + if (counters != null && counters.stub != null) { + counters.stub.inc(); + } result = newInstance(HotSpotBackend.NEW_INSTANCE, hub); } - profileAllocation("instance", size, typeContext); - return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + profileAllocation("instance", size, typeContext, options); + return verifyOop(result); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub); @Snippet public static Object allocateInstancePIC(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, - @ConstantParameter Register threadRegister, - @ConstantParameter boolean constantSize, @ConstantParameter String typeContext) { + @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { // Klass must be initialized by the time the first instance is allocated, therefore we can // just load it from the corresponding cell and avoid the resolution check. We have to use a // fixed load though, to prevent it from floating above the initialization. KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - return allocateInstance(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext); + return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters)); } @Snippet - public static Object allocateInstanceDynamic(Class type, Class classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister) { - if (probability(SLOW_PATH_PROBABILITY, type == null || DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) { + public static Object allocateInstanceDynamic(Class type, Class classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + if (probability(SLOW_PATH_PROBABILITY, type == null)) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + Class nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor()); + + if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - KlassPointer hub = ClassGetHubNode.readClass(type); + return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, options, counters, nonNullType)); + } + + private static Object allocateInstanceDynamicHelper(Class type, boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class nonNullType) { + KlassPointer hub = ClassGetHubNode.readClass(nonNullType); if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) { - if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(hub))) { - int layoutHelper = readLayoutHelper(hub); + KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor()); + + if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) { + int layoutHelper = readLayoutHelper(nonNullHub); /* * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number, * the instance size. This size is already passed through align_object_size and @@ -248,12 +270,12 @@ public class NewObjectSnippets implements Snippets { * allocated using the fastpath. */ if (probability(FAST_PATH_PROBABILITY, (layoutHelper & 1) == 0)) { - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); + Word prototypeMarkWord = nonNullHub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); /* * FIXME(je,ds): we should actually pass typeContext instead of "" but late * binding of parameters is not yet supported by the GraphBuilderPlugin system. */ - return allocateInstance(layoutHelper, hub, prototypeMarkWord, fillContents, threadRegister, false, ""); + return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters); } } } @@ -267,28 +289,34 @@ public class NewObjectSnippets implements Snippets { @Snippet public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + // Primitive array types are eagerly pre-resolved. We can use a floating load. KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); } @Snippet public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { - KlassPointer picHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + // We need to resolve array type. While element type is guaranteed to be initialized, we + // cannot guarantee initialization of the array class if NewArrayInstance comes from + // canonicalization of DynamicNewArrayInstance. + KlassPointer picHub = ResolveConstantSnippets.pureInitializeKlass(hub); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); } @Snippet public static Object allocateArray(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { - Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); + return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } - private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, - @ConstantParameter Register threadRegister, - @ConstantParameter boolean maybeUnroll, String typeContext, boolean skipNegativeCheck) { + private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister, + boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, OptionValues options, Counters counters) { Object result; int alignment = wordSize(); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); @@ -300,40 +328,43 @@ public class NewObjectSnippets implements Snippets { probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, true); - newarray_loopInit.inc(); - result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, true); + if (counters != null && counters.arrayLoopInit != null) { + counters.arrayLoopInit.inc(); + } + result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters); } else { result = newArray(HotSpotBackend.NEW_ARRAY, hub, length, fillContents); } - profileAllocation("array", allocationSize, typeContext); + profileAllocation("array", allocationSize, typeContext, options); return result; } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length, boolean fillContents); public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class); public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE = new ForeignCallDescriptor("dynamic_new_instance", Object.class, Class.class); - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object dynamicNewArrayStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class elementType, int length); public static Object dynamicNewInstanceStub(Class elementType) { return dynamicNewInstanceStubCall(DYNAMIC_NEW_INSTANCE, elementType); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object dynamicNewInstanceStubCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class elementType); @Snippet public static Object allocateArrayDynamic(Class elementType, Class voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord) { - Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord); + @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { + Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, options, counters); return result; } private static Object allocateArrayDynamicImpl(Class elementType, Class voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind, - int knownLayoutHelper, Word prototypeMarkWord) { + int knownLayoutHelper, Word prototypeMarkWord, OptionValues options, Counters counters) { /* * We only need the dynamic check for void when we have no static information from * knownElementKind. @@ -344,10 +375,15 @@ public class NewObjectSnippets implements Snippets { } KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION); - if (probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, klass.isNull() || length < 0)) { + if (klass.isNull()) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(klass); + KlassPointer nonNullKlass = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + + if (length < 0) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(nonNullKlass); //@formatter:off // from src/share/vm/oops/klass.hpp: // @@ -364,8 +400,8 @@ public class NewObjectSnippets implements Snippets { int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); - Object result = allocateArrayImpl(klass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, options, counters); + return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } /** @@ -376,18 +412,18 @@ public class NewObjectSnippets implements Snippets { Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { - dims.writeInt(i * 4, dimensions[i], INIT_LOCATION); + dims.writeInt(i * 4, dimensions[i], LocationIdentity.init()); } return newArrayCall(HotSpotBackend.NEW_MULTI_ARRAY, hub, rank, dims); } @Snippet public static Object newmultiarrayPIC(KlassPointer hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) { - KlassPointer hubPIC = ResolveConstantSnippets.resolveKlassConstant(hub); - return newmultiarray(hubPIC, rank, dimensions); + KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); + return newmultiarray(picHub, rank, dimensions); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newArrayCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int rank, Word dims); /** @@ -406,15 +442,15 @@ public class NewObjectSnippets implements Snippets { * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ - private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { - fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, useSnippetCounters); + private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, counters); } - private static void fillMemory(long value, int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { + private static void fillMemory(long value, int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { ReplacementsUtil.runtimeAssert((size & 0x7) == 0, "unaligned object size"); int offset = startOffset; if ((offset & 0x7) != 0) { - memory.writeInt(offset, (int) value, INIT_LOCATION); + memory.writeInt(offset, (int) value, LocationIdentity.init()); offset += 4; } ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset"); @@ -423,31 +459,32 @@ public class NewObjectSnippets implements Snippets { // This case handles arrays of constant length. Instead of having a snippet variant for // each length, generate a chain of stores of maximum length. Once it's inlined the // break statement will trim excess stores. - if (useSnippetCounters) { - new_seqInit.inc(); + if (counters != null && counters.instanceSeqInit != null) { + counters.instanceSeqInit.inc(); } + explodeLoop(); for (int i = 0; i < MAX_UNROLLED_OBJECT_ZEROING_STORES; i++, offset += 8) { if (offset == size) { break; } - memory.initializeLong(offset, value, INIT_LOCATION); + memory.initializeLong(offset, value, LocationIdentity.init()); } } else { // Use Word instead of int to avoid extension to long in generated code - Word off = Word.signed(offset); + Word off = WordFactory.signed(offset); if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { - if (useSnippetCounters) { - new_seqInit.inc(); + if (counters != null && counters.instanceSeqInit != null) { + counters.instanceSeqInit.inc(); } explodeLoop(); } else { - if (useSnippetCounters) { - new_loopInit.inc(); + if (counters != null && counters.instanceLoopInit != null) { + counters.instanceLoopInit.inc(); } } for (; off.rawValue() < size; off = off.add(8)) { - memory.initializeLong(off, value, INIT_LOCATION); + memory.initializeLong(off, value, LocationIdentity.init()); } } } @@ -462,8 +499,8 @@ public class NewObjectSnippets implements Snippets { * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ - private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { - fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, useSnippetCounters); + private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, counters); } /** @@ -471,31 +508,31 @@ public class NewObjectSnippets implements Snippets { * since they can't be compiled in stubs. */ public static Object formatObjectForStub(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord) { - return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, false); + return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, null); } /** * Formats some allocated memory with an object header and zeroes out the rest. */ - protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean useSnippetCounters) { + protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) { Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, useSnippetCounters); + zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { - fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, useSnippetCounters); + fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } - MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, INIT_LOCATION); - return memory.toObject(); + MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init()); + return memory.toObjectNonNull(); } @Snippet protected static void verifyHeap(@ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); Word topValue = readTlabTop(thread); - if (!topValue.equal(Word.zero())) { + if (!topValue.equal(WordFactory.zero())) { Word topValueContents = topValue.readWord(0, MARK_WORD_LOCATION); - if (topValueContents.equal(Word.zero())) { + if (topValueContents.equal(WordFactory.zero())) { AssertionSnippets.vmMessageC(AssertionSnippets.ASSERTION_VM_MESSAGE_C, true, cstring("overzeroing of TLAB detected"), 0L, 0L, 0L); } } @@ -505,43 +542,61 @@ public class NewObjectSnippets implements Snippets { * Formats some allocated memory with an object header and zeroes out the rest. */ public static Object formatArray(KlassPointer hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll, - boolean useSnippetCounters) { - memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, INIT_LOCATION); + Counters counters) { + memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init()); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field * is not null */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, useSnippetCounters); + zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { - fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, useSnippetCounters); + fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters); } - MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, INIT_LOCATION); - return memory.toObject(); + MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init()); + return memory.toObjectNonNull(); + } + + static class Counters { + Counters(SnippetCounter.Group.Factory factory) { + Group newInstance = factory.createSnippetCounterGroup("NewInstance"); + Group newArray = factory.createSnippetCounterGroup("NewArray"); + instanceSeqInit = new SnippetCounter(newInstance, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); + instanceLoopInit = new SnippetCounter(newInstance, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + arrayLoopInit = new SnippetCounter(newArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + stub = new SnippetCounter(newInstance, "stub", "alloc and zeroing via stub"); + } + + final SnippetCounter instanceSeqInit; + final SnippetCounter instanceLoopInit; + final SnippetCounter arrayLoopInit; + final SnippetCounter stub; } public static class Templates extends AbstractTemplates { - private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", TLAB_TOP_LOCATION, TLAB_END_LOCATION); private final SnippetInfo verifyHeap = snippet(NewObjectSnippets.class, "verifyHeap"); private final GraalHotSpotVMConfig config; + private final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) { + super(options, providers, providers.getSnippetReflection(), target); this.config = config; + counters = new Counters(factory); } /** @@ -554,7 +609,8 @@ public class NewObjectSnippets implements Snippets { ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph); int size = instanceSize(type); - SnippetInfo snippet = GeneratePIC.getValue() ? allocateInstancePIC : allocateInstance; + OptionValues localOptions = graph.getOptions(); + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? allocateInstancePIC : allocateInstance; Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("size", size); args.add("hub", hub); @@ -562,7 +618,9 @@ public class NewObjectSnippets implements Snippets { args.addConst("fillContents", newInstanceNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("constantSize", true); - args.addConst("typeContext", HotspotSnippetsOptions.ProfileAllocations.getValue() ? type.toJavaName(false) : ""); + args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : ""); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); @@ -581,8 +639,9 @@ public class NewObjectSnippets implements Snippets { final int headerSize = getArrayBaseOffset(elementKind); int log2ElementSize = CodeUtil.log2(HotSpotJVMCIRuntimeProvider.getArrayIndexScale(elementKind)); + OptionValues localOptions = graph.getOptions(); SnippetInfo snippet; - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(localOptions)) { if (elementType.isPrimitive()) { snippet = allocatePrimitiveArrayPIC; } else { @@ -603,7 +662,9 @@ public class NewObjectSnippets implements Snippets { args.addConst("fillContents", newArrayNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("maybeUnroll", length.isConstant()); - args.addConst("typeContext", HotspotSnippetsOptions.ProfileAllocations.getValue() ? arrayType.toJavaName(false) : ""); + args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : ""); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); @@ -611,12 +672,15 @@ public class NewObjectSnippets implements Snippets { public void lower(DynamicNewInstanceNode newInstanceNode, HotSpotRegistersProvider registers, LoweringTool tool) { Arguments args = new Arguments(allocateInstanceDynamic, newInstanceNode.graph().getGuardsStage(), tool.getLoweringStage()); + OptionValues localOptions = newInstanceNode.getOptions(); args.add("type", newInstanceNode.getInstanceType()); ValueNode classClass = newInstanceNode.getClassClass(); assert classClass != null; args.add("classClass", classClass); args.addConst("fillContents", newInstanceNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args); @@ -624,6 +688,7 @@ public class NewObjectSnippets implements Snippets { public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = newArrayNode.graph(); + OptionValues localOptions = graph.getOptions(); Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage()); args.add("elementType", newArrayNode.getElementType()); ValueNode voidClass = newArrayNode.getVoidClass(); @@ -644,6 +709,8 @@ public class NewObjectSnippets implements Snippets { args.addConst("knownLayoutHelper", 0); } args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord()); + args.addConst("options", localOptions); + args.addConst("counters", counters); SnippetTemplate template = template(args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } @@ -654,6 +721,7 @@ public class NewObjectSnippets implements Snippets { public void lower(NewMultiArrayNode newmultiarrayNode, LoweringTool tool) { StructuredGraph graph = newmultiarrayNode.graph(); + OptionValues localOptions = graph.getOptions(); int rank = newmultiarrayNode.dimensionCount(); ValueNode[] dims = new ValueNode[rank]; for (int i = 0; i < newmultiarrayNode.dimensionCount(); i++) { @@ -662,7 +730,7 @@ public class NewObjectSnippets implements Snippets { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph); - SnippetInfo snippet = GeneratePIC.getValue() ? newmultiarrayPIC : newmultiarray; + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? newmultiarrayPIC : newmultiarray; Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.addConst("rank", rank); @@ -688,13 +756,4 @@ public class NewObjectSnippets implements Snippets { } } } - - private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null; - private static final SnippetCounter new_seqInit = new SnippetCounter(countersNew, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); - private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub"); - - private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null; - private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewArray, "stub", "alloc and zeroing via stub"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java index 7e6252df6d3..c9a467a9a98 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import java.lang.reflect.Method; +import org.graalvm.compiler.core.common.type.AbstractPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; @@ -61,6 +61,18 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu super(TYPE, invokeKind, targetMethod, bci, returnStamp, receiver); } + @Override + protected Stamp computeStamp(ValueNode object) { + if (getConcreteType(object.stamp()) != null) { + return AbstractPointerStamp.pointerNonNull(object.stamp()); + } + /* + * If this call can't be intrinsified don't report a non-null stamp, otherwise the stamp + * would change when this is lowered back to an invoke and we might lose a null check. + */ + return AbstractPointerStamp.pointerMaybeNull(object.stamp()); + } + @Override @SuppressWarnings("try") protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) { @@ -79,6 +91,7 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu } assert snippetGraph != null : "ObjectCloneSnippets should be installed"; + assert getConcreteType(stamp()) != null; return lowerReplacement((StructuredGraph) snippetGraph.copy(), tool); } assert false : "unhandled array type " + type.getComponentType().getJavaKind(); @@ -86,7 +99,7 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu Assumptions assumptions = graph().getAssumptions(); type = getConcreteType(getObject().stamp()); if (type != null) { - StructuredGraph newGraph = new StructuredGraph(AllowAssumptions.from(assumptions != null), INVALID_COMPILATION_ID); + StructuredGraph newGraph = new StructuredGraph.Builder(graph().getOptions(), AllowAssumptions.ifNonNull(assumptions)).build(); ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp()))); NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); newGraph.addAfterFixed(newGraph.start(), newInstance); @@ -98,10 +111,12 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu newGraph.addBeforeFixed(returnNode, load); newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load))); } + assert getConcreteType(stamp()) != null; return lowerReplacement(newGraph, tool); } } } + assert getConcreteType(stamp()) == null; return null; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java index 6556bd91064..fe6ef1fc232 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; - import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; @@ -47,7 +44,7 @@ import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; -@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "This node can be lowered to a call", size = SIZE_20) +@NodeInfo public final class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(ReflectionGetCallerClassNode.class); @@ -80,7 +77,7 @@ public final class ReflectionGetCallerClassNode extends MacroStateSplitNode impl /** * If inlining is deep enough this method returns a {@link ConstantNode} of the caller class by - * walking the the stack. + * walking the stack. * * @param metaAccess * @return ConstantNode of the caller class, or null diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java index b72577f8a5a..43eedc6669b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java @@ -22,18 +22,19 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +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.vm.ci.meta.JavaKind; @@ -62,9 +63,9 @@ public class SHA2Substitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); - Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); + Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.sha2ImplCompressStub(bufAddr, stateAddr); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java index 0abda014a92..95ecd5b55d7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java @@ -22,18 +22,19 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +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.vm.ci.meta.JavaKind; @@ -62,9 +63,9 @@ public class SHA5Substitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); - Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); + Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.sha5ImplCompressStub(bufAddr, stateAddr); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java index 7d389f087c2..18d101fb16c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java @@ -22,18 +22,19 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +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.vm.ci.meta.JavaKind; @@ -62,9 +63,9 @@ public class SHASubstitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); - Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); + Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.shaImplCompressStub(bufAddr, stateAddr); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java index 434ae81a515..6e079c1c166 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java @@ -28,12 +28,12 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.debug.StringToBytesNode; import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -41,6 +41,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; 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.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; @@ -73,8 +74,8 @@ public class StringToBytesSnippets implements Snippets { private final SnippetInfo create; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); create = snippet(StringToBytesSnippets.class, "transform", NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java index e80bb98c19d..bb720f1629e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.LocationIdentity.any; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_OSTHREAD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION; 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 org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; @@ -45,6 +45,9 @@ import org.graalvm.compiler.word.Word; @ClassSubstitution(Thread.class) public class ThreadSubstitutions { + /** + * hidden in 9. + */ @MethodSubstitution(isStatic = false, optional = true) public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { Word javaThread = CurrentJavaThreadNode.get(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java index b112d1ae3b9..47e256d50dd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_SUPER_CHECK_OFFSET_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.METASPACE_ARRAY_LENGTH_LOCATION; @@ -47,6 +46,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.TypeCheckHints; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.word.Word; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -59,44 +59,44 @@ import jdk.vm.ci.meta.MetaAccessProvider; */ public class TypeCheckSnippetUtils { - static boolean checkSecondarySubType(KlassPointer t, KlassPointer s) { + static boolean checkSecondarySubType(KlassPointer t, KlassPointer sNonNull, Counters counters) { // if (S.cache == T) return true - if (s.readKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { - cacheHit.inc(); + if (sNonNull.readKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { + counters.cacheHit.inc(); return true; } - return checkSelfAndSupers(t, s); + return checkSelfAndSupers(t, sNonNull, counters); } - static boolean checkUnknownSubType(KlassPointer t, KlassPointer s) { + static boolean checkUnknownSubType(KlassPointer t, KlassPointer sNonNull, Counters counters) { // int off = T.offset int superCheckOffset = t.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION); boolean primary = superCheckOffset != secondarySuperCacheOffset(INJECTED_VMCONFIG); // if (T = S[off]) return true - if (s.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { + if (sNonNull.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { if (primary) { - cacheHit.inc(); + counters.cacheHit.inc(); } else { - displayHit.inc(); + counters.displayHit.inc(); } return true; } // if (off != &cache) return false if (primary) { - displayMiss.inc(); + counters.displayMiss.inc(); return false; } - return checkSelfAndSupers(t, s); + return checkSelfAndSupers(t, sNonNull, counters); } - private static boolean checkSelfAndSupers(KlassPointer t, KlassPointer s) { + private static boolean checkSelfAndSupers(KlassPointer t, KlassPointer s, Counters counters) { // if (T == S) return true if (s.equal(t)) { - T_equals_S.inc(); + counters.equalsSecondary.inc(); return true; } @@ -106,14 +106,43 @@ public class TypeCheckSnippetUtils { for (int i = 0; i < length; i++) { if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) { s.writeKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), t, SECONDARY_SUPER_CACHE_LOCATION); - secondariesHit.inc(); + counters.secondariesHit.inc(); return true; } } - secondariesMiss.inc(); + counters.secondariesMiss.inc(); return false; } + static class Counters { + final SnippetCounter hintsHit; + final SnippetCounter hintsMiss; + final SnippetCounter exactHit; + final SnippetCounter exactMiss; + final SnippetCounter isNull; + final SnippetCounter cacheHit; + final SnippetCounter secondariesHit; + final SnippetCounter secondariesMiss; + final SnippetCounter displayHit; + final SnippetCounter displayMiss; + final SnippetCounter equalsSecondary; + + Counters(SnippetCounter.Group.Factory factory) { + Group group = factory.createSnippetCounterGroup("TypeCheck"); + hintsHit = new SnippetCounter(group, "hintsHit", "hit a hint type"); + hintsMiss = new SnippetCounter(group, "hintsMiss", "missed a hint type"); + exactHit = new SnippetCounter(group, "exactHit", "exact type test succeeded"); + exactMiss = new SnippetCounter(group, "exactMiss", "exact type test failed"); + isNull = new SnippetCounter(group, "isNull", "object tested was null"); + cacheHit = new SnippetCounter(group, "cacheHit", "secondary type cache hit"); + secondariesHit = new SnippetCounter(group, "secondariesHit", "secondaries scan succeeded"); + secondariesMiss = new SnippetCounter(group, "secondariesMiss", "secondaries scan failed"); + displayHit = new SnippetCounter(group, "displayHit", "primary type test succeeded"); + displayMiss = new SnippetCounter(group, "displayMiss", "primary type test failed"); + equalsSecondary = new SnippetCounter(group, "T_equals_S", "object type was equal to secondary type"); + } + } + /** * A set of type check hints ordered by decreasing probabilities. */ @@ -158,18 +187,4 @@ public class TypeCheckSnippetUtils { static KlassPointer loadSecondarySupersElement(Word metaspaceArray, int index) { return KlassPointer.fromWord(metaspaceArray.readWord(metaspaceArrayBaseOffset(INJECTED_VMCONFIG) + index * wordSize(), SECONDARY_SUPERS_ELEMENT_LOCATION)); } - - private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("TypeCheck") : null; - static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type"); - static final SnippetCounter hintsMiss = new SnippetCounter(counters, "hintsMiss", "missed a hint type"); - static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded"); - static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed"); - static final SnippetCounter isNull = new SnippetCounter(counters, "isNull", "object tested was null"); - static final SnippetCounter cacheHit = new SnippetCounter(counters, "cacheHit", "secondary type cache hit"); - static final SnippetCounter secondariesHit = new SnippetCounter(counters, "secondariesHit", "secondaries scan succeeded"); - static final SnippetCounter secondariesMiss = new SnippetCounter(counters, "secondariesMiss", "secondaries scan failed"); - static final SnippetCounter displayHit = new SnippetCounter(counters, "displayHit", "primary type test succeeded"); - static final SnippetCounter displayMiss = new SnippetCounter(counters, "displayMiss", "primary type test failed"); - static final SnippetCounter T_equals_S = new SnippetCounter(counters, "T_equals_S", "object type was equal to secondary type"); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java index 0eef6871a4e..12543b80c54 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java @@ -28,9 +28,10 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; @@ -55,11 +56,11 @@ public class UnsafeLoadSnippets implements Snippets { private final SnippetInfo unsafeLoad = snippet(UnsafeLoadSnippets.class, "lowerUnsafeLoad"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } - public void lower(UnsafeLoadNode load, LoweringTool tool) { + public void lower(RawLoadNode load, LoweringTool tool) { Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", load.object()); args.add("offset", load.offset()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java index 526e9a572c9..1cf65814e61 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; +import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale; @@ -43,19 +43,16 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_P import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; -import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; @@ -63,9 +60,10 @@ import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -78,17 +76,21 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.Log; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.replacements.nodes.DirectStoreNode; -import org.graalvm.compiler.word.Pointer; -import org.graalvm.compiler.word.Unsigned; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.Unsigned; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; @@ -96,41 +98,55 @@ import jdk.vm.ci.meta.JavaKind; public class WriteBarrierSnippets implements Snippets { - private static final SnippetCounter.Group countersWriteBarriers = SnippetCounters.getValue() ? new SnippetCounter.Group("WriteBarriers") : null; - private static final SnippetCounter serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); - private static final SnippetCounter g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers"); - private static final SnippetCounter g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers"); - private static final SnippetCounter g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers"); - private static final SnippetCounter g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); - private static final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", - "Number of effective G1 Post Write Barriers (after passing the XOR test)"); - private static final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", - "Number of effective G1 Post Write Barriers (after passing the NULL test)"); - private static final SnippetCounter g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); + static class Counters { + Counters(SnippetCounter.Group.Factory factory) { + Group countersWriteBarriers = factory.createSnippetCounterGroup("WriteBarriers"); + serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); + g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers"); + g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers"); + g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers"); + g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); + g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the XOR test)"); + g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the NULL test)"); + g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); + + } + + final SnippetCounter serialWriteBarrierCounter; + final SnippetCounter g1AttemptedPreWriteBarrierCounter; + final SnippetCounter g1EffectivePreWriteBarrierCounter; + final SnippetCounter g1ExecutedPreWriteBarrierCounter; + final SnippetCounter g1AttemptedPostWriteBarrierCounter; + final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter; + final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter; + final SnippetCounter g1ExecutedPostWriteBarrierCounter; + } public static final LocationIdentity GC_CARD_LOCATION = NamedLocationIdentity.mutable("GC-Card"); public static final LocationIdentity GC_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Log"); public static final LocationIdentity GC_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Index"); - private static void serialWriteBarrier(Pointer ptr) { - serialWriteBarrierCounter.inc(); + private static void serialWriteBarrier(Pointer ptr, Counters counters) { + counters.serialWriteBarrierCounter.inc(); final long startAddress = GraalHotSpotVMConfigNode.cardTableAddress(); Word base = (Word) ptr.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG)); if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) { base.writeByte((int) startAddress, (byte) 0, GC_CARD_LOCATION); } else { - base.writeByte(Word.unsigned(startAddress), (byte) 0, GC_CARD_LOCATION); + base.writeByte(WordFactory.unsigned(startAddress), (byte) 0, GC_CARD_LOCATION); } } @Snippet - public static void serialImpreciseWriteBarrier(Object object) { - serialWriteBarrier(Word.objectToTrackedPointer(object)); + public static void serialImpreciseWriteBarrier(Object object, @ConstantParameter Counters counters) { + serialWriteBarrier(Word.objectToTrackedPointer(object), counters); } @Snippet - public static void serialPreciseWriteBarrier(Address address) { - serialWriteBarrier(Word.fromAddress(address)); + public static void serialPreciseWriteBarrier(Address address, @ConstantParameter Counters counters) { + serialWriteBarrier(Word.fromAddress(address), counters); } @Snippet @@ -154,26 +170,27 @@ public class WriteBarrierSnippets implements Snippets { @Snippet public static void g1PreWriteBarrier(Address address, Object object, Object expectedObject, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck, - @ConstantParameter Register threadRegister, @ConstantParameter boolean trace) { + @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, @ConstantParameter Counters counters) { if (nullCheck) { NullCheckNode.nullCheck(address); } Word thread = registerAsWord(threadRegister); verifyOop(object); Object fixedExpectedObject = FixedValueAnchorNode.getObject(expectedObject); - Pointer field = Word.fromAddress(address); + Word field = Word.fromAddress(address); Pointer previousOop = Word.objectToTrackedPointer(fixedExpectedObject); byte markingValue = thread.readByte(g1SATBQueueMarkingOffset(INJECTED_VMCONFIG)); int gcCycle = 0; if (trace) { - gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0); + Pointer gcTotalCollectionsAddress = WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)); + gcCycle = (int) gcTotalCollectionsAddress.readLong(0); log(trace, "[%d] G1-Pre Thread %p Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue()); log(trace, "[%d] G1-Pre Thread %p Expected Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(fixedExpectedObject).rawValue()); log(trace, "[%d] G1-Pre Thread %p Field %p\n", gcCycle, thread.rawValue(), field.rawValue()); log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue); log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L); } - g1AttemptedPreWriteBarrierCounter.inc(); + counters.g1AttemptedPreWriteBarrierCounter.inc(); // If the concurrent marker is enabled, the barrier is issued. if (probability(NOT_FREQUENT_PROBABILITY, markingValue != (byte) 0)) { // If the previous value has to be loaded (before the write), the load is issued. @@ -185,10 +202,10 @@ public class WriteBarrierSnippets implements Snippets { verifyOop(previousOop.toObject()); } } - g1EffectivePreWriteBarrierCounter.inc(); + counters.g1EffectivePreWriteBarrierCounter.inc(); // If the previous value is null the barrier should not be issued. if (probability(FREQUENT_PROBABILITY, previousOop.notEqual(0))) { - g1ExecutedPreWriteBarrierCounter.inc(); + counters.g1ExecutedPreWriteBarrierCounter.inc(); // If the thread-local SATB buffer is full issue a native call which will // initialize a new one and add the entry. Word indexAddress = thread.add(g1SATBQueueIndexOffset(INJECTED_VMCONFIG)); @@ -209,7 +226,7 @@ public class WriteBarrierSnippets implements Snippets { @Snippet public static void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter boolean usePrecise, @ConstantParameter Register threadRegister, - @ConstantParameter boolean trace) { + @ConstantParameter boolean trace, @ConstantParameter Counters counters) { Word thread = registerAsWord(threadRegister); Object fixedValue = FixedValueAnchorNode.getObject(value); verifyOop(object); @@ -223,7 +240,8 @@ public class WriteBarrierSnippets implements Snippets { } int gcCycle = 0; if (trace) { - gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0); + Pointer gcTotalCollectionsAddress = WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)); + gcCycle = (int) gcTotalCollectionsAddress.readLong(0); log(trace, "[%d] G1-Post Thread: %p Object: %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue()); log(trace, "[%d] G1-Post Thread: %p Field: %p\n", gcCycle, thread.rawValue(), oop.rawValue()); } @@ -241,27 +259,27 @@ public class WriteBarrierSnippets implements Snippets { if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) { displacement = (int) startAddress; } else { - cardBase = cardBase.add(Word.unsigned(startAddress)); + cardBase = cardBase.add(WordFactory.unsigned(startAddress)); } Word cardAddress = (Word) cardBase.add(displacement); - g1AttemptedPostWriteBarrierCounter.inc(); + counters.g1AttemptedPostWriteBarrierCounter.inc(); if (probability(FREQUENT_PROBABILITY, xorResult.notEqual(0))) { - g1EffectiveAfterXORPostWriteBarrierCounter.inc(); + counters.g1EffectiveAfterXORPostWriteBarrierCounter.inc(); // If the written value is not null continue with the barrier addition. if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); - g1EffectiveAfterNullPostWriteBarrierCounter.inc(); + counters.g1EffectiveAfterNullPostWriteBarrierCounter.inc(); // If the card is already dirty, (hence already enqueued) skip the insertion. if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue(INJECTED_VMCONFIG))) { MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION); byte cardByteReload = cardAddress.readByte(0, GC_CARD_LOCATION); if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue(INJECTED_VMCONFIG))) { - log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), Word.unsigned(cardByte).rawValue()); + log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), WordFactory.unsigned((int) cardByte).rawValue()); cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); - g1ExecutedPostWriteBarrierCounter.inc(); + counters.g1ExecutedPostWriteBarrierCounter.inc(); // If the thread local card queue is full, issue a native call which will // initialize a new one and add the card entry. @@ -301,16 +319,16 @@ public class WriteBarrierSnippets implements Snippets { int header = arrayBaseOffset(JavaKind.Object); for (int i = startIndex; i < length; i++) { - long address = dstAddr + header + (i * scale); - Pointer oop = Word.objectToTrackedPointer(Word.unsigned(address).readObject(0, BarrierType.NONE)); + Word address = WordFactory.pointer(dstAddr + header + (i * scale)); + Pointer oop = Word.objectToTrackedPointer(address.readObject(0, BarrierType.NONE)); verifyOop(oop.toObject()); if (oop.notEqual(0)) { if (indexValue != 0) { indexValue = indexValue - wordSize(); - Word logAddress = bufferAddress.add(Word.unsigned(indexValue)); + Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue)); // Log the object to be marked as well as update the SATB's buffer next index. logAddress.writeWord(0, oop, GC_LOG_LOCATION); - indexAddress.writeWord(0, Word.unsigned(indexValue), GC_INDEX_LOCATION); + indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION); } else { g1PreBarrierStub(G1WBPRECALL, oop.toObject()); } @@ -339,7 +357,7 @@ public class WriteBarrierSnippets implements Snippets { long count = end - start + 1; while (count-- > 0) { - Word cardAddress = Word.unsigned((start + cardStart) + count); + Word cardAddress = WordFactory.unsigned((start + cardStart) + count); byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); // If the card is already dirty, (hence already enqueued) skip the insertion. if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue(INJECTED_VMCONFIG))) { @@ -351,11 +369,11 @@ public class WriteBarrierSnippets implements Snippets { // initialize a new one and add the card entry. if (indexValue != 0) { indexValue = indexValue - wordSize(); - Word logAddress = bufferAddress.add(Word.unsigned(indexValue)); + Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue)); // Log the object to be scanned as well as update // the card queue's next index. logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION); - indexAddress.writeWord(0, Word.unsigned(indexValue), GC_INDEX_LOCATION); + indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION); } else { g1PostBarrierStub(G1WBPOSTCALL, cardAddress); } @@ -386,10 +404,12 @@ public class WriteBarrierSnippets implements Snippets { private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION); private final CompressEncoding oopEncoding; + private final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, CompressEncoding oopEncoding) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, CompressEncoding oopEncoding) { + super(options, providers, providers.getSnippetReflection(), target); this.oopEncoding = oopEncoding; + this.counters = new Counters(factory); } public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) { @@ -402,6 +422,7 @@ public class WriteBarrierSnippets implements Snippets { OffsetAddressNode address = (OffsetAddressNode) writeBarrier.getAddress(); args.add("object", address.getBase()); } + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); } @@ -426,14 +447,15 @@ public class WriteBarrierSnippets implements Snippets { ValueNode expected = writeBarrierPre.getExpectedObject(); if (expected != null && expected.stamp() instanceof NarrowOopStamp) { assert oopEncoding != null; - expected = CompressionNode.uncompress(expected, oopEncoding); + expected = HotSpotCompressionNode.uncompress(expected, oopEncoding); } args.add("expectedObject", expected); args.addConst("doLoad", writeBarrierPre.doLoad()); args.addConst("nullCheck", writeBarrierPre.getNullCheck()); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); + args.addConst("trace", traceBarrier(writeBarrierPre.graph())); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args); } @@ -450,14 +472,15 @@ public class WriteBarrierSnippets implements Snippets { ValueNode expected = readBarrier.getExpectedObject(); if (expected != null && expected.stamp() instanceof NarrowOopStamp) { assert oopEncoding != null; - expected = CompressionNode.uncompress(expected, oopEncoding); + expected = HotSpotCompressionNode.uncompress(expected, oopEncoding); } args.add("expectedObject", expected); args.addConst("doLoad", readBarrier.doLoad()); args.addConst("nullCheck", false); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); + args.addConst("trace", traceBarrier(readBarrier.graph())); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args); } @@ -480,13 +503,14 @@ public class WriteBarrierSnippets implements Snippets { ValueNode value = writeBarrierPost.getValue(); if (value.stamp() instanceof NarrowOopStamp) { assert oopEncoding != null; - value = CompressionNode.uncompress(value, oopEncoding); + value = HotSpotCompressionNode.uncompress(value, oopEncoding); } args.add("value", value); args.addConst("usePrecise", writeBarrierPost.usePrecise()); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); + args.addConst("trace", traceBarrier(writeBarrierPost.graph())); + args.addConst("counters", counters); template(args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args); } @@ -530,9 +554,10 @@ public class WriteBarrierSnippets implements Snippets { } } - public static boolean traceBarrier() { - return GraalOptions.GCDebugStartCycle.getValue() > 0 && - ((int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0) > GraalOptions.GCDebugStartCycle.getValue()); + public static boolean traceBarrier(StructuredGraph graph) { + return GraalOptions.GCDebugStartCycle.getValue(graph.getOptions()) > 0 && + ((int) ((Pointer) WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG))).readLong(0) > GraalOptions.GCDebugStartCycle.getValue( + graph.getOptions())); } /** @@ -544,7 +569,7 @@ public class WriteBarrierSnippets implements Snippets { public static void validateObject(Object parent, Object child) { if (verifyOops(INJECTED_VMCONFIG) && child != null && !validateOop(VALIDATE_OBJECT, parent, child)) { log(true, "Verification ERROR, Parent: %p Child: %p\n", Word.objectToTrackedPointer(parent).rawValue(), Word.objectToTrackedPointer(child).rawValue()); - DirectObjectStoreNode.storeObject(null, 0, 0, null, LocationIdentity.any(), JavaKind.Object); + VMErrorNode.vmError("Verification ERROR, Parent: %p\n", Word.objectToTrackedPointer(parent).rawValue()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java index 7b0f000f6ed..3205bcaa5f5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -113,8 +114,8 @@ public class ResolveConstantSnippets implements Snippets { private final SnippetInfo initializeKlass = snippet(ResolveConstantSnippets.class, "initializeKlass"); private final SnippetInfo pureInitializeKlass = snippet(ResolveConstantSnippets.class, "pureInitializeKlass"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(ResolveConstantNode resolveConstantNode, LoweringTool tool) { @@ -148,7 +149,7 @@ public class ResolveConstantSnippets implements Snippets { args.add("constant", value); SnippetTemplate template = template(args); - template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, tool, args); + template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args); assert resolveConstantNode.hasNoUsages(); if (!resolveConstantNode.isDeleted()) { @@ -186,7 +187,7 @@ public class ResolveConstantSnippets implements Snippets { args.add("method", method); args.add("klassHint", resolveMethodAndLoadCountersNode.getHub()); SnippetTemplate template = template(args); - template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, tool, args); + template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, args); assert resolveMethodAndLoadCountersNode.hasNoUsages(); if (!resolveMethodAndLoadCountersNode.isDeleted()) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java index 50618b2e513..8f4e370020f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java @@ -29,7 +29,6 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -58,6 +57,7 @@ import org.graalvm.compiler.nodes.memory.MemoryNode; 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.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.JavaConstant; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java index 803ee73d6e5..61170a8427c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java @@ -22,22 +22,21 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import jdk.vm.ci.meta.JavaKind; +import static org.graalvm.word.LocationIdentity.any; -import static org.graalvm.compiler.core.common.LocationIdentity.any; - -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; +import org.graalvm.word.LocationIdentity; + +import jdk.vm.ci.meta.JavaKind; @NodeInfo -public final class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable { +public final class ArrayCopyNode extends BasicArrayCopyNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(ArrayCopyNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java index 4111f702394..99591564e3d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.hotspot.replacements.arraycopy; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.JavaKind; -import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static org.graalvm.word.LocationIdentity.any; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.InputType; @@ -37,6 +36,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; +import org.graalvm.word.LocationIdentity; @NodeInfo(allowedUsageTypes = InputType.Memory) public final class ArrayCopySlowPathNode extends BasicArrayCopyNode { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java index 08eab361382..f583500b80b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_SUPER_CHECK_OFFSET_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION; @@ -39,13 +38,11 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probabil import java.lang.reflect.Method; import java.util.EnumMap; -import java.util.Map; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -60,19 +57,25 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.word.Word; +import org.graalvm.util.UnmodifiableEconomicMap; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -85,64 +88,64 @@ import jdk.vm.ci.meta.ResolvedJavaType; public class ArrayCopySnippets implements Snippets { - private static int checkArrayType(KlassPointer hub) { - int layoutHelper = readLayoutHelper(hub); + private static int checkArrayType(KlassPointer nonNullHub) { + int layoutHelper = readLayoutHelper(nonNullHub); if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return layoutHelper; } - private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) { + private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length, Counters counters) { if (probability(SLOW_PATH_PROBABILITY, srcPos < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, destPos < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, length < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, srcPos > ArrayLengthNode.arrayLength(src) - length)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, destPos > ArrayLengthNode.arrayLength(dest) - length)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - checkSuccessCounter.inc(); + counters.checkSuccessCounter.inc(); } @Snippet - public static void arraycopyZeroLengthIntrinsic(Object src, int srcPos, Object dest, int destPos, int length) { + public static void arraycopyZeroLengthIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); checkArrayType(srcHub); checkArrayType(destHub); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); - zeroLengthStaticCounter.inc(); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); + counters.zeroLengthStaticCounter.inc(); } @Snippet public static void arraycopyExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter SnippetCounter counter, - @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } } @@ -152,7 +155,7 @@ public class ArrayCopySnippets implements Snippets { */ @Snippet public static void arraycopyPredictedExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, - @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); @@ -160,33 +163,33 @@ public class ArrayCopySnippets implements Snippets { if (probability(SLOW_PATH_PROBABILITY, srcHub != destHub)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } } @Snippet public static void arraycopyPredictedObjectWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass, - @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { if (length > 0) { KlassPointer srcHub = loadHub(PiNode.asNonNullObject(nonNullSrc)); KlassPointer destHub = loadHub(PiNode.asNonNullObject(nonNullDest)); if (probability(FAST_PATH_PROBABILITY, srcHub == destHub || destHub == objectArrayKlass)) { counter.inc(); copiedCounter.add(length); - predictedObjectArrayCopyFastPathCounter.inc(); - predictedObjectArrayCopyFastPathCopiedCounter.add(length); + counters.predictedObjectArrayCopyFastPathCounter.inc(); + counters.predictedObjectArrayCopyFastPathCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { - predictedObjectArrayCopySlowPathCounter.inc(); - predictedObjectArrayCopySlowPathCopiedCounter.add(length); + counters.predictedObjectArrayCopySlowPathCounter.inc(); + counters.predictedObjectArrayCopySlowPathCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } } @@ -198,19 +201,19 @@ public class ArrayCopySnippets implements Snippets { */ @Snippet public static void arraycopySlowPathIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, KlassPointer predictedKlass, @ConstantParameter JavaKind elementKind, - @ConstantParameter SnippetInfo slowPath, @ConstantParameter Object slowPathArgument) { + @ConstantParameter SnippetInfo slowPath, @ConstantParameter Object slowPathArgument, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); checkArrayType(srcHub); checkArrayType(destHub); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } ArrayCopySlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, predictedKlass, elementKind, slowPath, slowPathArgument); } @@ -219,34 +222,35 @@ public class ArrayCopySnippets implements Snippets { * Snippet for unrolled arraycopy. */ @Snippet - public static void arraycopyUnrolledIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter int unrolledLength, @ConstantParameter JavaKind elementKind) { + public static void arraycopyUnrolledIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter int unrolledLength, @ConstantParameter JavaKind elementKind, + @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } ArrayCopyUnrollNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, unrolledLength, elementKind); } @Snippet - public static void checkcastArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length) { + public static void checkcastArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantParameter Counters counters) { if (length > 0) { KlassPointer destKlass = loadHub(nonNullDest); KlassPointer srcKlass = loadHub(nonNullSrc); if (probability(SLOW_PATH_PROBABILITY, srcKlass == destKlass)) { // no storecheck required. - objectCheckcastSameTypeCounter.inc(); - objectCheckcastSameTypeCopiedCounter.add(length); + counters.objectCheckcastSameTypeCounter.inc(); + counters.objectCheckcastSameTypeCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { KlassPointer destElemKlass = destKlass.readKlassPointer(arrayClassElementOffset(INJECTED_VMCONFIG), OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION); - Word superCheckOffset = Word.signed(destElemKlass.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION)); - objectCheckcastCounter.inc(); - objectCheckcastCopiedCounter.add(length); + Word superCheckOffset = WordFactory.signed(destElemKlass.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION)); + counters.objectCheckcastCounter.inc(); + counters.objectCheckcastCopiedCounter.add(length); int copiedElements = CheckcastArrayCopyCallNode.checkcastArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, superCheckOffset, destElemKlass, false); if (copiedElements != 0) { /* @@ -261,7 +265,7 @@ public class ArrayCopySnippets implements Snippets { } @Snippet - public static void arraycopyGeneric(Object src, int srcPos, Object dest, int destPos, int length) { + public static void arraycopyGeneric(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); @@ -269,19 +273,19 @@ public class ArrayCopySnippets implements Snippets { if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) { int layoutHelper = checkArrayType(srcHub); final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace(INJECTED_VMCONFIG)) == 0); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (probability(FAST_PATH_PROBABILITY, isObjectArray)) { - genericObjectExactCallCounter.inc(); - genericObjectExactCallCopiedCounter.add(length); + counters.genericObjectExactCallCounter.inc(); + counters.genericObjectExactCallCopiedCounter.add(length); ArrayCopyCallNode.disjointArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, JavaKind.Object); } else { - genericPrimitiveCallCounter.inc(); - genericPrimitiveCallCopiedCounter.add(length); + counters.genericPrimitiveCallCounter.inc(); + counters.genericPrimitiveCallCopiedCounter.add(length); UnsafeArrayCopyNode.arraycopyPrimitive(nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper); } } else { - SystemArraycopyCounter.inc(); - SystemArraycopyCopiedCounter.add(length); + counters.systemArraycopyCounter.inc(); + counters.systemArraycopyCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } } @@ -302,8 +306,8 @@ public class ArrayCopySnippets implements Snippets { ExplodeLoopNode.explodeLoop(); for (int iteration = 0; iteration < length; iteration++) { if (i >= 0) { - Object a = UnsafeLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); - DirectObjectStoreNode.storeObject(nonNullDest, arrayBaseOffset, i + (long) destPos * scale, a, arrayLocation, elementKind); + Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); + RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false); i -= scale; } } @@ -313,78 +317,103 @@ public class ArrayCopySnippets implements Snippets { ExplodeLoopNode.explodeLoop(); for (int iteration = 0; iteration < length; iteration++) { if (i < end) { - Object a = UnsafeLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); - DirectObjectStoreNode.storeObject(nonNullDest, arrayBaseOffset, i + (long) destPos * scale, a, arrayLocation, elementKind); + Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); + RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false); i += scale; } } } } - private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null; - private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess"); - private static final SnippetCounter checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE"); + static class Counters { + final SnippetCounter checkSuccessCounter; + final SnippetCounter checkAIOOBECounter; - private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy") : null; + final SnippetCounter objectCheckcastCounter; + final SnippetCounter objectCheckcastSameTypeCounter; + final SnippetCounter predictedObjectArrayCopySlowPathCounter; + final SnippetCounter predictedObjectArrayCopyFastPathCounter; - private static final SnippetCounter objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); - private static final SnippetCounter objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + final SnippetCounter genericPrimitiveCallCounter; + final SnippetCounter genericObjectExactCallCounter; + final SnippetCounter systemArraycopyCounter; - private static final EnumMap arraycopyCallCounters = new EnumMap<>(JavaKind.class); - private static final EnumMap arraycopyCounters = new EnumMap<>(JavaKind.class); + final SnippetCounter zeroLengthStaticCounter; + final SnippetCounter zeroLengthDynamicCounter; + final SnippetCounter nonZeroLengthDynamicCounter; - private static final EnumMap arraycopyCallCopiedCounters = new EnumMap<>(JavaKind.class); - private static final EnumMap arraycopyCopiedCounters = new EnumMap<>(JavaKind.class); + final SnippetCounter nonZeroLengthDynamicCopiedCounter; + final SnippetCounter genericPrimitiveCallCopiedCounter; + final SnippetCounter genericObjectExactCallCopiedCounter; + final SnippetCounter systemArraycopyCopiedCounter; - static void createArraycopyCounter(JavaKind kind) { - arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); - arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + final SnippetCounter objectCheckcastCopiedCounter; + final SnippetCounter objectCheckcastSameTypeCopiedCounter; + final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter; + final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter; - arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); - arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + final EnumMap arraycopyCallCounters = new EnumMap<>(JavaKind.class); + final EnumMap arraycopyCounters = new EnumMap<>(JavaKind.class); + + final EnumMap arraycopyCallCopiedCounters = new EnumMap<>(JavaKind.class); + final EnumMap arraycopyCopiedCounters = new EnumMap<>(JavaKind.class); + + Counters(SnippetCounter.Group.Factory factory) { + final Group checkCounters = factory.createSnippetCounterGroup("System.arraycopy checkInputs"); + final Group counters = factory.createSnippetCounterGroup("System.arraycopy"); + final Group copiedCounters = factory.createSnippetCounterGroup("System.arraycopy copied elements"); + final Group lengthCounters = factory.createSnippetCounterGroup("System.arraycopy 0-length checks"); + + checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess"); + checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE"); + + objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); + objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); + predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays"); + predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); + genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); + systemArraycopyCounter = new SnippetCounter(counters, "genericObject", "call to System.arraycopy"); + + zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-lengthcopy static", "arraycopy where the length is statically 0"); + zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0"); + nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); + + nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); + genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); + genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); + systemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy"); + + objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); + objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); + predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}", + "used System.arraycopy slow path for predicted Object[] arrays"); + predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + createArraycopyCounter(JavaKind.Byte, counters, copiedCounters); + createArraycopyCounter(JavaKind.Boolean, counters, copiedCounters); + createArraycopyCounter(JavaKind.Char, counters, copiedCounters); + createArraycopyCounter(JavaKind.Short, counters, copiedCounters); + createArraycopyCounter(JavaKind.Int, counters, copiedCounters); + createArraycopyCounter(JavaKind.Long, counters, copiedCounters); + createArraycopyCounter(JavaKind.Float, counters, copiedCounters); + createArraycopyCounter(JavaKind.Double, counters, copiedCounters); + createArraycopyCounter(JavaKind.Object, counters, copiedCounters); + } + + void createArraycopyCounter(JavaKind kind, Group counters, Group copiedCounters) { + arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); + arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + + arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); + arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + } } - static { - createArraycopyCounter(JavaKind.Byte); - createArraycopyCounter(JavaKind.Boolean); - createArraycopyCounter(JavaKind.Char); - createArraycopyCounter(JavaKind.Short); - createArraycopyCounter(JavaKind.Int); - createArraycopyCounter(JavaKind.Long); - createArraycopyCounter(JavaKind.Float); - createArraycopyCounter(JavaKind.Double); - createArraycopyCounter(JavaKind.Object); - } - - private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); - private static final SnippetCounter genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); - private static final SnippetCounter SystemArraycopyCounter = new SnippetCounter(counters, "genericObject", "call to System.arraycopy"); - - private static final SnippetCounter.Group lengthCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy 0-length checks") : null; - - private static final SnippetCounter zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-lengthcopy static", "arraycopy where the length is statically 0"); - private static final SnippetCounter zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0"); - private static final SnippetCounter nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); - - private static final SnippetCounter.Group copiedCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy copied elements") : null; - - private static final SnippetCounter nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); - private static final SnippetCounter genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); - private static final SnippetCounter genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); - private static final SnippetCounter SystemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy"); - - private static final SnippetCounter objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); - private static final SnippetCounter objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}", - "used System.arraycopy slow path for predicted Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); - public static class Templates extends SnippetTemplate.AbstractTemplates { - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); + this.counters = new Counters(factory); } private ResolvedJavaMethod originalArraycopy() throws GraalError { @@ -414,6 +443,8 @@ public class ArrayCopySnippets implements Snippets { private final SnippetInfo arraycopyUnrolledWorkSnippet = snippet("arraycopyUnrolledWork"); + private final Counters counters; + protected SnippetInfo snippet(String methodName) { SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, LocationIdentity.any()); info.setOriginalMethod(originalArraycopy()); @@ -538,9 +569,10 @@ public class ArrayCopySnippets implements Snippets { } else if (snippetInfo == arraycopyExactIntrinsicSnippet || snippetInfo == arraycopyPredictedExactIntrinsicSnippet) { assert componentKind != null; args.addConst("elementKind", componentKind); - args.addConst("counter", arraycopyCallCounters.get(componentKind)); - args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(componentKind)); + args.addConst("counter", counters.arraycopyCallCounters.get(componentKind)); + args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(componentKind)); } + args.addConst("counters", counters); instantiate(args, arraycopy); } @@ -564,8 +596,9 @@ public class ArrayCopySnippets implements Snippets { } if (snippetInfo == arraycopyPredictedObjectWorkSnippet) { args.add("objectArrayKlass", arraycopy.getPredictedKlass()); - args.addConst("counter", arraycopyCallCounters.get(JavaKind.Object)); - args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(JavaKind.Object)); + args.addConst("counter", counters.arraycopyCallCounters.get(JavaKind.Object)); + args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(JavaKind.Object)); + args.addConst("counters", counters); } instantiate(args, arraycopy); } @@ -597,8 +630,8 @@ public class ArrayCopySnippets implements Snippets { private void instantiate(Arguments args, BasicArrayCopyNode arraycopy) { StructuredGraph graph = arraycopy.graph(); SnippetTemplate template = template(args); - Map replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); - for (Node originalNode : replacements.keySet()) { + UnmodifiableEconomicMap replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args, false); + for (Node originalNode : replacements.getKeys()) { if (originalNode instanceof Invoke) { Invoke invoke = (Invoke) replacements.get(originalNode); assert invoke.asNode().graph() == graph; @@ -612,17 +645,18 @@ public class ArrayCopySnippets implements Snippets { if (arraycopy.stateDuring() != null) { newInvoke.setStateDuring(arraycopy.stateDuring()); } else { - assert arraycopy.stateAfter() != null; + assert arraycopy.stateAfter() != null : arraycopy; newInvoke.setStateAfter(arraycopy.stateAfter()); } graph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke); } else if (originalNode instanceof ArrayCopySlowPathNode) { ArrayCopySlowPathNode slowPath = (ArrayCopySlowPathNode) replacements.get(originalNode); - assert arraycopy.stateAfter() != null; - slowPath.setStateAfter(arraycopy.stateAfter()); + assert arraycopy.stateAfter() != null : arraycopy; + assert slowPath.stateAfter() == arraycopy.stateAfter(); slowPath.setBci(arraycopy.getBci()); } } + GraphUtil.killCFG(arraycopy); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java index f0729b4e8e8..7bd998024d3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java @@ -24,9 +24,8 @@ package org.graalvm.compiler.hotspot.replacements.arraycopy; import jdk.vm.ci.meta.JavaKind; -import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static org.graalvm.word.LocationIdentity.any; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; @@ -39,6 +38,7 @@ import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 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; @NodeInfo(allowedUsageTypes = InputType.Memory) public class ArrayCopyUnrollNode extends ArrayRangeWriteNode implements MemoryCheckpoint.Single, Lowerable, MemoryAccess { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java index 4f98f071012..8853e1a3b66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java @@ -28,7 +28,6 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -51,6 +50,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.compiler.word.Word; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.JavaKind; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java index d904f2ae6d1..83c7c4f9f10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java @@ -22,11 +22,10 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_200; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_200; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_256; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; +import static org.graalvm.word.LocationIdentity.any; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; @@ -40,10 +39,11 @@ import org.graalvm.compiler.nodes.memory.MemoryNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_200, size = SIZE_200) +@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_256, size = SIZE_64) public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single, MemoryAccess { public static final NodeClass TYPE = NodeClass.create(UnsafeArrayCopyNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java index 69cb5730036..f98ac7a8154 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java @@ -39,24 +39,24 @@ import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.extended.UnsafeCopyNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; -import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.word.ObjectAccess; -import org.graalvm.compiler.word.Unsigned; -import org.graalvm.compiler.word.Word; - +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Unsigned; +import org.graalvm.word.WordFactory; +import org.graalvm.compiler.replacements.Snippets; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; @@ -205,7 +205,7 @@ public class UnsafeArrayCopySnippets implements Snippets { /** * For this kind, Object, we want to avoid write barriers between writes, but instead have them - * at the end of the snippet. This is done by using {@link DirectObjectStoreNode}, and rely on + * at the end of the snippet. This is done by using {@link RawStoreNode}, and rely on * {@link WriteBarrierAdditionPhase} to put write barriers after the {@link UnsafeArrayCopyNode} * with kind Object. */ @@ -218,14 +218,14 @@ public class UnsafeArrayCopySnippets implements Snippets { if (src == dest && srcPos < destPos) { // bad aliased case long start = (long) (length - 1) * scale; for (long i = start; i >= 0; i -= scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind); + Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); + RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false); } } else { long end = (long) length * scale; for (long i = 0; i < end; i += scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind); + Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); + RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false); } } } @@ -235,15 +235,15 @@ public class UnsafeArrayCopySnippets implements Snippets { int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); - Unsigned vectorSize = Word.unsigned(VECTOR_SIZE); - Unsigned srcOffset = Word.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize); - Unsigned destOffset = Word.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize); + Unsigned vectorSize = WordFactory.unsigned(VECTOR_SIZE); + Unsigned srcOffset = WordFactory.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize); + Unsigned destOffset = WordFactory.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize); Unsigned destStart = destOffset; - Unsigned destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize)); + Unsigned destEnd = destOffset.add(WordFactory.unsigned(length).shiftLeft(log2ElementSize)); Unsigned destVectorEnd = null; Unsigned nonVectorBytes = null; - Unsigned sizeInBytes = Word.unsigned(length).shiftLeft(log2ElementSize); + Unsigned sizeInBytes = WordFactory.unsigned(length).shiftLeft(log2ElementSize); if (supportsUnalignedMemoryAccess) { nonVectorBytes = sizeInBytes.unsignedRemainder(vectorSize); destVectorEnd = destEnd; @@ -284,8 +284,8 @@ public class UnsafeArrayCopySnippets implements Snippets { private final SnippetInfo[] arraycopySnippets; private final SnippetInfo genericPrimitiveSnippet; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); arraycopySnippets = new SnippetInfo[JavaKind.values().length]; arraycopySnippets[JavaKind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean"); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java index 87ce20ab8f9..28822a2aa9a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -113,8 +114,8 @@ public class ProbabilisticProfileSnippets implements Snippets { private final SnippetInfo profileBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileBackedgeWithProbability"); private final SnippetInfo profileConditionalBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileConditionalBackedgeWithProbability"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java index 98c5588b4d5..4b63201c786 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java @@ -46,6 +46,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -95,8 +96,8 @@ public class ProfileSnippets implements Snippets { private final SnippetInfo profileBackedge = snippet(ProfileSnippets.class, "profileBackedge"); private final SnippetInfo profileConditionalBackedge = snippet(ProfileSnippets.class, "profileConditionalBackedge"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, HotSpotProviders providers, TargetDescription target) { + super(options, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java index 9877dc7cd94..bff470d18a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -36,8 +37,8 @@ import jdk.vm.ci.code.Register; */ public class ArrayStoreExceptionStub extends CreateExceptionStub { - public ArrayStoreExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createArrayStoreException", providers, linkage); + public ArrayStoreExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createArrayStoreException", options, providers, linkage); } @Override @@ -47,7 +48,7 @@ public class ArrayStoreExceptionStub extends CreateExceptionStub { } @Snippet - private static Object createArrayStoreException(Object object, @ConstantParameter Register threadRegister) { + private static Object createArrayStoreException(@Snippet.NonNullParameter Object object, @ConstantParameter Register threadRegister) { KlassPointer klass = HotSpotReplacementsUtil.loadHub(object); return createException(threadRegister, ArrayStoreException.class, klass); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java index d9a7aa18f1d..57ccd5dcefe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -36,8 +37,8 @@ import jdk.vm.ci.code.Register; */ public class ClassCastExceptionStub extends CreateExceptionStub { - public ClassCastExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createClassCastException", providers, linkage); + public ClassCastExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createClassCastException", options, providers, linkage); } @Override @@ -47,7 +48,7 @@ public class ClassCastExceptionStub extends CreateExceptionStub { } @Snippet - private static Object createClassCastException(Object object, KlassPointer targetKlass, @ConstantParameter Register threadRegister) { + private static Object createClassCastException(@Snippet.NonNullParameter Object object, KlassPointer targetKlass, @ConstantParameter Register threadRegister) { KlassPointer objKlass = HotSpotReplacementsUtil.loadHub(object); return createException(threadRegister, ClassCastException.class, objKlass, targetKlass); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java index 64360137f71..09b757d8a15 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.hotspot.stubs; -import static org.graalvm.compiler.core.common.LocationIdentity.any; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; 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.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import org.graalvm.compiler.api.replacements.Fold; @@ -40,6 +40,7 @@ import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.nodes.CStringConstant; import org.graalvm.compiler.word.Word; @@ -50,8 +51,8 @@ import jdk.vm.ci.code.Register; */ public class CreateExceptionStub extends SnippetStub { - protected CreateExceptionStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(snippetMethodName, providers, linkage); + protected CreateExceptionStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetMethodName, options, providers, linkage); } @Fold diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java deleted file mode 100644 index acfb4e151e6..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java +++ /dev/null @@ -1,302 +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.hotspot.stubs; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNPACK_FRAMES; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode.fetchUnrollInfo; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeRegisterAsWord; -import static org.graalvm.compiler.hotspot.stubs.UncommonTrapStub.STACK_BANG_LOCATION; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.EnterUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveCurrentStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveDeoptimizedStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.PushInterpreterFrameNode; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.TargetDescription; - -/** - * Deoptimization stub. - * - * This is the entry point for code which is returning to a de-optimized frame. - * - * The steps taken by this frame are as follows: - * - *
  11. push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all - * potentially live registers (at a pollpoint many registers can be live). - * - *
  12. call the C routine: Deoptimization::fetch_unroll_info (this function returns information - * about the number and size of interpreter frames which are equivalent to the frame which is being - * deoptimized) - * - *
  13. deallocate the unpack frame, restoring only results values. Other volatile registers will now - * be captured in the vframeArray as needed. - * - *
  14. deallocate the deoptimization frame - * - *
  15. in a loop using the information returned in the previous step push new interpreter frames - * (take care to propagate the return values through each new frame pushed) - * - *
  16. create a dummy "unpack_frame" and save the return values (O0, O1, F0) - * - *
  17. call the C routine: Deoptimization::unpack_frames (this function lays out values on the - * interpreter frame which was just created) - * - *
  18. deallocate the dummy unpack_frame - * - *
  19. ensure that all the return values are correctly set and then do a return to the interpreter - * entry point - * - *

    - * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet - * because we change the current stack layout and so the code is very sensitive to register - * allocation. - */ -public class DeoptimizationStub extends SnippetStub { - - private final TargetDescription target; - - public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(DeoptimizationStub.class, "deoptimizationHandler", providers, linkage); - this.target = target; - assert PreferGraalStubs.getValue(); - } - - @Override - public boolean preservesRegisters() { - return false; - } - - @Override - protected Object getConstantParameterValue(int index, String name) { - switch (index) { - case 0: - return providers.getRegisters().getThreadRegister(); - case 1: - return providers.getRegisters().getStackPointerRegister(); - default: - throw GraalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); - } - } - - /** - * Deoptimization handler for normal deoptimization - * {@link GraalHotSpotVMConfig#deoptimizationUnpackDeopt}. - */ - @Snippet - private static void deoptimizationHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { - final Word thread = registerAsWord(threadRegister); - final long registerSaver = SaveAllRegistersNode.saveAllRegisters(); - - final Word unrollBlock = fetchUnrollInfo(registerSaver, deoptimizationUnpackDeopt(INJECTED_VMCONFIG)); - - deoptimizationCommon(stackPointerRegister, thread, registerSaver, unrollBlock); - } - - static void deoptimizationCommon(Register stackPointerRegister, final Word thread, final long registerSaver, final Word unrollBlock) { - // Pop all the frames we must move/replace. - // - // Frame picture (youngest to oldest) - // 1: self-frame - // 2: deoptimizing frame - // 3: caller of deoptimizing frame (could be compiled/interpreted). - - // Pop self-frame. - LeaveCurrentStackFrameNode.leaveCurrentStackFrame(registerSaver); - - // Load the initial info we should save (e.g. frame pointer). - final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset(INJECTED_VMCONFIG)); - - // Pop deoptimized frame. - final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(INJECTED_VMCONFIG)); - LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); - - /* - * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for - * total size of the interpreter frames plus shadow page size. Bang one page at a time - * because large sizes can bang beyond yellow and red zones. - * - * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. - */ - final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset(INJECTED_VMCONFIG)); - final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(INJECTED_VMCONFIG); - Word stackPointer = readRegister(stackPointerRegister); - - for (int i = 1; i < bangPages; i++) { - stackPointer.writeInt((-i * pageSize()) + stackBias(INJECTED_VMCONFIG), 0, STACK_BANG_LOCATION); - } - - // Load number of interpreter frames. - final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset(INJECTED_VMCONFIG)); - - // Load address of array of frame sizes. - final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset(INJECTED_VMCONFIG)); - - // Load address of array of frame PCs. - final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset(INJECTED_VMCONFIG)); - - /* - * Get the current stack pointer (sender's original SP) before adjustment so that we can - * save it in the skeletal interpreter frame. - */ - Word senderSp = readRegister(stackPointerRegister); - - // Adjust old interpreter frame to make space for new frame's extra Java locals. - final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset(INJECTED_VMCONFIG)); - writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment)); - - for (int i = 0; i < numberOfFrames; i++) { - final Word frameSize = frameSizes.readWord(i * wordSize()); - final Word framePc = framePcs.readWord(i * wordSize()); - - // Push an interpreter frame onto the stack. - PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo); - - // Get the current stack pointer (sender SP) and pass it to next frame. - senderSp = readRegister(stackPointerRegister); - } - - // Get final return address. - final Word framePc = framePcs.readWord(numberOfFrames * wordSize()); - - /* - * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an - * unknown alignment we need to align it here before calling C++ code. - */ - final Word senderFp = initialInfo; - EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp, registerSaver); - - final int mode = unrollBlock.readInt(deoptimizationUnrollBlockUnpackKindOffset(INJECTED_VMCONFIG)); - unpackFrames(UNPACK_FRAMES, thread, mode); - - LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(registerSaver); - } - - /** - * Reads the value of the passed register as a Word. - */ - private static Word readRegister(Register register) { - return registerAsWord(register, false, false); - } - - /** - * Writes the value of the passed register. - * - * @param value value the register should be set to - */ - private static void writeRegister(Register register, Word value) { - writeRegisterAsWord(register, value); - } - - @Fold - static int stackShadowPages(@InjectedParameter GraalHotSpotVMConfig config) { - return config.useStackBanging ? config.stackShadowPages : 0; - } - - /** - * Returns the stack bias for the host architecture. - * - * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. - * - * @return stack bias - */ - @Deprecated - @Fold - static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) { - return config.stackBias; - } - - @Fold - static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; - } - - @Fold - static int deoptimizationUnrollBlockCallerAdjustmentOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockCallerAdjustmentOffset; - } - - @Fold - static int deoptimizationUnrollBlockNumberOfFramesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockNumberOfFramesOffset; - } - - @Fold - static int deoptimizationUnrollBlockTotalFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockTotalFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockUnpackKindOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockUnpackKindOffset; - } - - @Fold - static int deoptimizationUnrollBlockFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFramePcsOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFramePcsOffset; - } - - @Fold - static int deoptimizationUnrollBlockInitialInfoOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockInitialInfoOffset; - } - - @Fold - static int deoptimizationUnpackDeopt(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackDeopt; - } - - @Fold - static int deoptimizationUnpackUncommonTrap(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackUncommonTrap; - } - - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) - public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java index bd435f90a32..775b15f670c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java @@ -41,6 +41,7 @@ import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -48,7 +49,9 @@ import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 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.vm.ci.code.Register; @@ -62,8 +65,8 @@ import jdk.vm.ci.code.Register; */ public class ExceptionHandlerStub extends SnippetStub { - public ExceptionHandlerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("exceptionHandler", providers, linkage); + public ExceptionHandlerStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("exceptionHandler", options, providers, linkage); } /** @@ -78,18 +81,21 @@ public class ExceptionHandlerStub extends SnippetStub { @Override protected Object getConstantParameterValue(int index, String name) { - assert index == 2; - return providers.getRegisters().getThreadRegister(); + if (index == 2) { + return providers.getRegisters().getThreadRegister(); + } + assert index == 3; + return options; } @Snippet - private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister) { + private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { Word thread = registerAsWord(threadRegister); checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG)); checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception); writeExceptionOop(thread, exception); writeExceptionPc(thread, exceptionPc); - if (logging()) { + if (logging(options)) { printf("handling exception %p (", Word.objectToTrackedPointer(exception).rawValue()); decipher(Word.objectToTrackedPointer(exception).rawValue()); printf(") at %p (", exceptionPc.rawValue()); @@ -102,7 +108,7 @@ public class ExceptionHandlerStub extends SnippetStub { Word handlerPc = exceptionHandlerForPc(EXCEPTION_HANDLER_FOR_PC, thread); - if (logging()) { + if (logging(options)) { printf("handler for exception %p at %p is at %p (", Word.objectToTrackedPointer(exception).rawValue(), exceptionPc.rawValue(), handlerPc.rawValue()); decipher(handlerPc.rawValue()); printf(")\n"); @@ -122,7 +128,7 @@ public class ExceptionHandlerStub extends SnippetStub { // This thread-local is only cleared in DEBUG builds of the VM // (see OptoRuntime::generate_exception_blob) Word currentExceptionPc = readExceptionPc(thread); - if (currentExceptionPc.notEqual(Word.zero())) { + if (currentExceptionPc.notEqual(WordFactory.zero())) { fatal("exception PC in thread must be zero, not %p", currentExceptionPc.rawValue()); } } @@ -136,27 +142,22 @@ public class ExceptionHandlerStub extends SnippetStub { } @Fold - static boolean logging() { - return StubOptions.TraceExceptionHandlerStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceExceptionHandlerStub.getValue(options); } /** - * Determines if either Java assertions are enabled for {@link ExceptionHandlerStub} or if this - * is a HotSpot build where the ASSERT mechanism is enabled. - *

    - * This first check relies on the per-class assertion status which is why this method must be in - * this class. + * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build + * where the ASSERT mechanism is enabled. */ @Fold @SuppressWarnings("all") static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) { - boolean enabled = false; - assert enabled = true; - return enabled || cAssertionsEnabled(config); + return Assertions.ENABLED || cAssertionsEnabled(config); } public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = newDescriptor(ExceptionHandlerStub.class, "exceptionHandlerForPc", Word.class, Word.class); - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = StubForeignCallNode.class) public static native Word exceptionHandlerForPc(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForPc, Word thread); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java index ef51bbdf472..2d3e8789438 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java @@ -30,8 +30,8 @@ import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +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.Debug; @@ -47,15 +47,18 @@ import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.replacements.GraphKit; 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.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; import jdk.vm.ci.hotspot.HotSpotSignature; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; @@ -99,9 +102,10 @@ public class ForeignCallStub extends Stub { * be re-executed. * @param killedLocations the memory locations killed by the stub call */ - public ForeignCallStub(HotSpotJVMCIRuntimeProvider runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, Transition transition, + public ForeignCallStub(OptionValues options, HotSpotJVMCIRuntimeProvider runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, + Transition transition, boolean reexecutable, LocationIdentity... killedLocations) { - super(providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L, + super(options, providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations)); this.jvmciRuntime = runtime; this.prependThread = prependThread; @@ -224,7 +228,7 @@ public class ForeignCallStub extends Stub { Class[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn()); - StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(options).name(toString()).compilationId(compilationId).build(); graph.disableUnsafeAccessTracking(); GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins()); @@ -239,15 +243,13 @@ public class ForeignCallStub extends Stub { } kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Initial stub graph"); - } + Debug.dump(Debug.VERBOSE_LEVEL, graph, "Initial stub graph"); kit.inlineInvokes(); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Stub graph before compilation"); - } + new RemoveValueProxyPhase().apply(graph); + + Debug.dump(Debug.VERBOSE_LEVEL, graph, "Stub graph before compilation"); return graph; } @@ -265,13 +267,14 @@ public class ForeignCallStub extends Stub { } private StubForeignCallNode createTargetCall(GraphKit kit, ParameterNode[] params, ReadRegisterNode thread) { + Stamp stamp = StampFactory.forKind(JavaKind.fromJavaClass(target.getDescriptor().getResultType())); if (prependThread) { ValueNode[] targetArguments = new ValueNode[1 + params.length]; targetArguments[0] = thread; System.arraycopy(params, 0, targetArguments, 1, params.length); - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments)); + return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), targetArguments)); } else { - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), params)); + return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), params)); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java index c30dda95f4c..d7018a1ef75 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java @@ -31,7 +31,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeShift; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeMask; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassLayoutHelperIntrinsic; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH; @@ -57,7 +57,9 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; 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.vm.ci.code.Register; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -70,8 +72,8 @@ import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; */ public class NewArrayStub extends SnippetStub { - public NewArrayStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("newArray", providers, linkage); + public NewArrayStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newArray", options, providers, linkage); } @Override @@ -81,14 +83,16 @@ public class NewArrayStub extends SnippetStub { Object[] args = new Object[count]; assert checkConstArg(3, "intArrayHub"); assert checkConstArg(4, "threadRegister"); + assert checkConstArg(5, "options"); args[3] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); args[4] = providers.getRegisters().getThreadRegister(); + args[5] = options; return args; } @Fold - static boolean logging() { - return StubOptions.TraceNewArrayStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceNewArrayStub.getValue(options); } /** @@ -101,13 +105,14 @@ public class NewArrayStub extends SnippetStub { * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newArray(KlassPointer hub, int length, boolean fillContents, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister) { - int layoutHelper = loadKlassLayoutHelperIntrinsic(hub); + private static Object newArray(KlassPointer hub, int length, boolean fillContents, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister, + @ConstantParameter OptionValues options) { + int layoutHelper = readLayoutHelper(hub); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int elementKind = (layoutHelper >> layoutHelperElementTypeShift(INJECTED_VMCONFIG)) & layoutHelperElementTypeMask(INJECTED_VMCONFIG); int sizeInBytes = computeArrayAllocationSize(length, wordSize(), headerSize, log2ElementSize); - if (logging()) { + if (logging(options)) { printf("newArray: element kind %d\n", elementKind); printf("newArray: array length %d\n", length); printf("newArray: array size %d\n", sizeInBytes); @@ -118,16 +123,16 @@ public class NewArrayStub extends SnippetStub { Word thread = registerAsWord(threadRegister); boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported(); if (inlineContiguousAllocationSupported && length >= 0 && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { - Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); + Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options)); if (memory.notEqual(0)) { - if (logging()) { + if (logging(options)) { printf("newArray: allocated new array at %p\n", memory.rawValue()); } return verifyObject( - formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord(INJECTED_VMCONFIG)), fillContents, false, false)); + formatArray(hub, sizeInBytes, length, headerSize, memory, WordFactory.unsigned(arrayPrototypeMarkWord(INJECTED_VMCONFIG)), fillContents, false, null)); } } - if (logging()) { + if (logging(options)) { printf("newArray: calling new_array_c\n"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java index b6a64dc4b8a..91a5acab1f1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.stubs; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode.compareAndSwap; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_END_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_TOP_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; @@ -37,7 +36,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeTlab; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassLayoutHelperIntrinsic; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.log2WordSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabEnd; @@ -79,8 +78,9 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.memory.address.RawAddressNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.Register; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -94,8 +94,8 @@ import jdk.vm.ci.meta.JavaKind; */ public class NewInstanceStub extends SnippetStub { - public NewInstanceStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("newInstance", providers, linkage); + public NewInstanceStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newInstance", options, providers, linkage); } @Override @@ -105,8 +105,10 @@ public class NewInstanceStub extends SnippetStub { Object[] args = new Object[count]; assert checkConstArg(1, "intArrayHub"); assert checkConstArg(2, "threadRegister"); + assert checkConstArg(3, "options"); args[1] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); args[2] = providers.getRegisters().getThreadRegister(); + args[3] = options; return args; } @@ -122,12 +124,12 @@ public class NewInstanceStub extends SnippetStub { writeTlabTop(thread, newTop); return top; } - return Word.zero(); + return WordFactory.zero(); } @Fold - static boolean logging() { - return StubOptions.TraceNewInstanceStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceNewInstanceStub.getValue(options); } /** @@ -138,17 +140,17 @@ public class NewInstanceStub extends SnippetStub { * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(KlassPointer hub, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister) { + private static Object newInstance(KlassPointer hub, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { /* * The type is known to be an instance so Klass::_layout_helper is the instance size as a * raw number */ - int sizeInBytes = loadKlassLayoutHelperIntrinsic(hub); Word thread = registerAsWord(threadRegister); boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported(); - if (!forceSlowPath() && inlineContiguousAllocationSupported) { + if (!forceSlowPath(options) && inlineContiguousAllocationSupported) { if (isInstanceKlassFullyInitialized(hub)) { - Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); + int sizeInBytes = readLayoutHelper(hub); + Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options)); if (memory.notEqual(0)) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); NewObjectSnippets.formatObjectForStub(hub, sizeInBytes, memory, prototypeMarkWord); @@ -157,7 +159,7 @@ public class NewInstanceStub extends SnippetStub { } } - if (logging()) { + if (logging(options)) { printf("newInstance: calling new_instance_c\n"); } @@ -173,19 +175,19 @@ public class NewInstanceStub extends SnippetStub { * @param sizeInBytes the size of the allocation * @param log specifies if logging is enabled * - * @return the newly allocated, uninitialized chunk of memory, or {@link Word#zero()} if the - * operation was unsuccessful + * @return the newly allocated, uninitialized chunk of memory, or {@link WordFactory#zero()} if + * the operation was unsuccessful */ static Word refillAllocate(Word thread, KlassPointer intArrayHub, int sizeInBytes, boolean log) { // If G1 is enabled, the "eden" allocation space is not the same always // and therefore we have to go to slowpath to allocate a new TLAB. if (useG1GC(INJECTED_VMCONFIG)) { - return Word.zero(); + return WordFactory.zero(); } if (!useTLAB(INJECTED_VMCONFIG)) { - return edenAllocate(Word.unsigned(sizeInBytes), log); + return edenAllocate(WordFactory.unsigned(sizeInBytes), log); } - Word intArrayMarkWord = Word.unsigned(tlabIntArrayMarkWord(INJECTED_VMCONFIG)); + Word intArrayMarkWord = WordFactory.unsigned(tlabIntArrayMarkWord(INJECTED_VMCONFIG)); int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords(INJECTED_VMCONFIG) * wordSize(); Word top = readTlabTop(thread); @@ -229,7 +231,7 @@ public class NewInstanceStub extends SnippetStub { // an int int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes >>> 2; int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; - NewObjectSnippets.formatArray(intArrayHub, 0, length, headerSize, top, intArrayMarkWord, false, false, false); + NewObjectSnippets.formatArray(intArrayHub, 0, length, headerSize, top, intArrayMarkWord, false, false, null); long allocated = thread.readLong(threadAllocatedBytesOffset(INJECTED_VMCONFIG), TLAB_THREAD_ALLOCATED_BYTES_LOCATION); allocated = allocated + top.subtract(readTlabStart(thread)).rawValue(); @@ -247,7 +249,7 @@ public class NewInstanceStub extends SnippetStub { return NewInstanceStub.allocate(thread, sizeInBytes); } else { - return Word.zero(); + return WordFactory.zero(); } } else { // Retain TLAB @@ -262,7 +264,7 @@ public class NewInstanceStub extends SnippetStub { TLAB_SLOW_ALLOCATIONS_LOCATION); } - return edenAllocate(Word.unsigned(sizeInBytes), log); + return edenAllocate(WordFactory.unsigned(sizeInBytes), log); } } @@ -271,36 +273,35 @@ public class NewInstanceStub extends SnippetStub { * * @param sizeInBytes the size of the chunk to allocate * @param log specifies if logging is enabled - * @return the allocated chunk or {@link Word#zero()} if allocation fails + * @return the allocated chunk or {@link WordFactory#zero()} if allocation fails */ public static Word edenAllocate(Word sizeInBytes, boolean log) { final long heapTopRawAddress = GraalHotSpotVMConfigNode.heapTopAddress(); final long heapEndRawAddress = GraalHotSpotVMConfigNode.heapEndAddress(); - Word heapTopAddress = Word.unsigned(heapTopRawAddress); - Word heapEndAddress = Word.unsigned(heapEndRawAddress); + Word heapTopAddress = WordFactory.unsigned(heapTopRawAddress); + Word heapEndAddress = WordFactory.unsigned(heapEndRawAddress); while (true) { Word heapTop = heapTopAddress.readWord(0, HEAP_TOP_LOCATION); Word newHeapTop = heapTop.add(sizeInBytes); if (newHeapTop.belowOrEqual(heapTop)) { - return Word.zero(); + return WordFactory.zero(); } Word heapEnd = heapEndAddress.readWord(0, HEAP_END_LOCATION); if (newHeapTop.aboveThan(heapEnd)) { - return Word.zero(); + return WordFactory.zero(); } - - if (compareAndSwap(RawAddressNode.address(heapTopAddress), heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) { + if (heapTopAddress.logicCompareAndSwapWord(0, heapTop, newHeapTop, HEAP_TOP_LOCATION)) { return heapTop; } } } @Fold - static boolean forceSlowPath() { - return StubOptions.ForceUseOfNewInstanceStub.getValue(); + static boolean forceSlowPath(OptionValues options) { + return StubOptions.ForceUseOfNewInstanceStub.getValue(options); } public static final ForeignCallDescriptor NEW_INSTANCE_C = newDescriptor(NewInstanceStub.class, "newInstanceC", void.class, Word.class, KlassPointer.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java index b5ba143de37..662bce4c731 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -35,8 +36,8 @@ import jdk.vm.ci.code.Register; */ public class NullPointerExceptionStub extends CreateExceptionStub { - public NullPointerExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createNullPointerException", providers, linkage); + public NullPointerExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createNullPointerException", options, providers, linkage); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java index 095680062ee..c162328ae94 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.AllocaNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import jdk.vm.ci.code.Register; @@ -37,8 +38,8 @@ import jdk.vm.ci.code.Register; */ public class OutOfBoundsExceptionStub extends CreateExceptionStub { - public OutOfBoundsExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createOutOfBoundsException", providers, linkage); + public OutOfBoundsExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createOutOfBoundsException", options, providers, linkage); } private static final int MAX_INT_STRING_SIZE = Integer.toString(Integer.MIN_VALUE).length(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java index b645d8944d2..ca2702cc4e3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java @@ -22,31 +22,35 @@ */ package org.graalvm.compiler.hotspot.stubs; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Method; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import org.graalvm.compiler.bytecode.BytecodeProvider; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; import org.graalvm.compiler.replacements.SnippetTemplate; @@ -71,8 +75,8 @@ public abstract class SnippetStub extends Stub implements Snippets { * this object * @param linkage linkage details for a call to the stub */ - public SnippetStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - this(null, snippetMethodName, providers, linkage); + public SnippetStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + this(null, snippetMethodName, options, providers, linkage); } /** @@ -84,21 +88,12 @@ public abstract class SnippetStub extends Stub implements Snippets { * {@code snippetDeclaringClass} * @param linkage linkage details for a call to the stub */ - public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(providers, linkage); + public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(options, providers, linkage); Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null); this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod); } - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean enabled = false; - assert enabled = true; - return enabled; - } - - public static final ThreadLocal SnippetGraphUnderConstruction = assertionsEnabled() ? new ThreadLocal<>() : null; - @Override @SuppressWarnings("try") protected StructuredGraph getGraph(CompilationIdentifier compilationId) { @@ -112,29 +107,25 @@ public abstract class SnippetStub extends Stub implements Snippets { // Stubs cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. - final StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, NO_PROFILING_INFO, compilationId); + final StructuredGraph graph = new StructuredGraph.Builder(options).method(method).compilationId(compilationId).build(); try (Scope outer = Debug.scope("SnippetStub", graph)) { graph.disableUnsafeAccessTracking(); - if (SnippetGraphUnderConstruction != null) { - assert SnippetGraphUnderConstruction.get() == null : SnippetGraphUnderConstruction.get().toString() + " " + graph; - SnippetGraphUnderConstruction.set(graph); - } + IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING); + GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), + providers.getConstantReflection(), providers.getConstantFieldProvider(), + config, OptimisticOptimizations.NONE, + initialIntrinsicContext); + instance.apply(graph); - try { - IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, providers.getReplacements().getReplacementBytecodeProvider(), INLINE_AFTER_PARSING); - GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), - providers.getConstantReflection(), providers.getConstantFieldProvider(), - config, OptimisticOptimizations.NONE, - initialIntrinsicContext); - instance.apply(graph); - - } finally { - if (SnippetGraphUnderConstruction != null) { - SnippetGraphUnderConstruction.set(null); + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { + int index = param.index(); + if (method.getParameterAnnotation(NonNullParameter.class, index) != null) { + param.setStamp(param.stamp().join(StampFactory.objectNonNull())); } } + new RemoveValueProxyPhase().apply(graph); graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); PhaseContext context = new PhaseContext(providers); @@ -147,6 +138,10 @@ public abstract class SnippetStub extends Stub implements Snippets { return graph; } + protected BytecodeProvider getReplacementsBytecodeProvider() { + return providers.getReplacements().getDefaultReplacementBytecodeProvider(); + } + protected boolean checkConstArg(int index, String expectedName) { assert method.getParameterAnnotation(ConstantParameter.class, index) != null : String.format("parameter %d of %s is expected to be constant", index, method.format("%H.%n(%p)")); LocalVariableTable lvt = method.getLocalVariableTable(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java index 8857bd417a6..54b49bc62bb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java @@ -25,20 +25,18 @@ package org.graalvm.compiler.hotspot.stubs; import static org.graalvm.compiler.core.GraalCompiler.emitBackEnd; import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugStubsAndSnippets; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; +import static org.graalvm.util.CollectionsUtil.allMatch; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.ListIterator; -import java.util.Set; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugConfig; import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; @@ -50,9 +48,11 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; import org.graalvm.compiler.lir.profiling.MoveProfilingPhase; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; @@ -77,8 +77,6 @@ import jdk.vm.ci.meta.TriState; */ public abstract class Stub { - private static final List stubs = new ArrayList<>(); - /** * The linkage information for a call to this stub from compiled code. */ @@ -92,11 +90,21 @@ public abstract class Stub { /** * The registers destroyed by this stub (from the caller's perspective). */ - private Set destroyedCallerRegisters; + private EconomicSet destroyedCallerRegisters; - public void initDestroyedCallerRegisters(Set registers) { + private static boolean checkRegisterSetEquivalency(EconomicSet a, EconomicSet b) { + if (a == b) { + return true; + } + if (a.size() != b.size()) { + return false; + } + return allMatch(a, e -> b.contains(e)); + } + + public void initDestroyedCallerRegisters(EconomicSet registers) { assert registers != null; - assert destroyedCallerRegisters == null || registers.equals(destroyedCallerRegisters) : "cannot redefine"; + assert destroyedCallerRegisters == null || checkRegisterSetEquivalency(registers, destroyedCallerRegisters) : "cannot redefine"; destroyedCallerRegisters = registers; } @@ -104,7 +112,7 @@ public abstract class Stub { * Gets the registers destroyed by this stub from a caller's perspective. These are the * temporaries of this stub and must thus be caller saved by a callers of this stub. */ - public Set getDestroyedCallerRegisters() { + public EconomicSet getDestroyedCallerRegisters() { assert destroyedCallerRegisters != null : "not yet initialized"; return destroyedCallerRegisters; } @@ -117,6 +125,7 @@ public abstract class Stub { return true; } + protected final OptionValues options; protected final HotSpotProviders providers; /** @@ -124,17 +133,10 @@ public abstract class Stub { * * @param linkage linkage details for a call to the stub */ - public Stub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + public Stub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { this.linkage = linkage; + this.options = options; this.providers = providers; - stubs.add(this); - } - - /** - * Gets an immutable view of all stubs that have been created. - */ - public static Collection getStubs() { - return Collections.unmodifiableList(stubs); } /** @@ -176,14 +178,16 @@ public abstract class Stub { @SuppressWarnings("try") public synchronized InstalledCode getCode(final Backend backend) { if (code == null) { - try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { + DebugConfig config = DebugStubsAndSnippets.getValue(options) ? DebugScope.getConfig() : Debug.silentConfig(); + try (Scope d = Debug.sandbox("CompilingStub", config, providers.getCodeCache(), debugScopeContext())) { CodeCacheProvider codeCache = providers.getCodeCache(); + CompilationResult compResult = buildCompilationResult(backend); try (Scope s = Debug.scope("CodeInstall", compResult)) { assert destroyedCallerRegisters != null; // Add a GeneratePIC check here later, we don't want to install // code if we don't have a corresponding VM global symbol. - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult); + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult); code = codeCache.installCode(null, compiledCode, null, null, false); } catch (Throwable e) { throw Debug.handle(e); @@ -199,7 +203,7 @@ public abstract class Stub { @SuppressWarnings("try") private CompilationResult buildCompilationResult(final Backend backend) { - CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue()); + CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue(options)); final StructuredGraph graph = getGraph(getStubCompilationId()); // Stubs cannot be recompiled so they cannot be compiled with assumptions @@ -275,12 +279,12 @@ public abstract class Stub { } protected Suites createSuites() { - Suites defaultSuites = providers.getSuites().getDefaultSuites(); + Suites defaultSuites = providers.getSuites().getDefaultSuites(options); return new Suites(new PhaseSuite<>(), defaultSuites.getMidTier(), defaultSuites.getLowTier()); } protected LIRSuites createLIRSuites() { - LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites()); + LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites(options)); ListIterator> moveProfiling = lirSuites.getPostAllocationOptimizationStage().findPhase(MoveProfilingPhase.class); if (moveProfiling != null) { moveProfiling.remove(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java index 87425f72781..c4db6e94c01 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.hotspot.stubs; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; //JaCoCo Exclude @@ -37,18 +37,18 @@ import org.graalvm.compiler.options.OptionValue; public class StubOptions { // @formatter:off @Option(help = "Trace execution of stub used to handle an exception thrown by a callee.", type = OptionType.Debug) - static final OptionValue TraceExceptionHandlerStub = new OptionValue<>(false); + static final OptionKey TraceExceptionHandlerStub = new OptionKey<>(false); @Option(help = "Trace execution of the stub that routes an exception to a handler in the calling frame.", type = OptionType.Debug) - static final OptionValue TraceUnwindStub = new OptionValue<>(false); + static final OptionKey TraceUnwindStub = new OptionKey<>(false); @Option(help = "Trace execution of slow path stub for array allocation.", type = OptionType.Debug) - static final OptionValue TraceNewArrayStub = new OptionValue<>(false); + static final OptionKey TraceNewArrayStub = new OptionKey<>(false); @Option(help = "Trace execution of slow path stub for non-array object allocation.", type = OptionType.Debug) - static final OptionValue TraceNewInstanceStub = new OptionValue<>(false); + static final OptionKey TraceNewInstanceStub = new OptionKey<>(false); @Option(help = "Force non-array object allocation to always use the slow path.", type = OptionType.Debug) - static final OptionValue ForceUseOfNewInstanceStub = new OptionValue<>(false); + static final OptionKey ForceUseOfNewInstanceStub = new OptionKey<>(false); //@formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java index 169a03ede3f..725bb138bf5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops; import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring; -import static org.graalvm.compiler.word.Word.unsigned; -import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -43,15 +42,16 @@ import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.replacements.Log; -import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.DeoptimizationAction; @@ -171,7 +171,7 @@ public class StubUtil { * Analyzes a given value and prints information about it to the log stream. */ public static void decipher(long value) { - vmMessageC(VM_MESSAGE_C, false, Word.zero(), value, 0L, 0L); + vmMessageC(VM_MESSAGE_C, false, WordFactory.zero(), value, 0L, 0L); } /** @@ -233,14 +233,14 @@ public class StubUtil { */ public static Object verifyObject(Object object) { if (verifyOops(INJECTED_VMCONFIG)) { - Word verifyOopCounter = Word.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG)); + Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG)); verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1); Pointer oop = Word.objectToTrackedPointer(object); if (object != null) { GuardingNode anchorNode = SnippetAnchorNode.anchor(); // make sure object is 'reasonable' - if (!oop.and(unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(unsigned(verifyOopBits(INJECTED_VMCONFIG)))) { + if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) { fatal("oop not in heap: %p", oop.rawValue()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java deleted file mode 100644 index 2c981eaee79..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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.stubs; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readPendingDeoptimization; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writePendingDeoptimization; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeRegisterAsWord; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; -import org.graalvm.compiler.nodes.NamedLocationIdentity; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.TargetDescription; - -/** - * Uncommon trap stub. - * - * This is the entry point for code which is returning to a de-optimized frame. - * - * The steps taken by this frame are as follows: - * - *

  20. push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all - * potentially live registers (at a pollpoint many registers can be live). - * - *
  21. call the C routine: Deoptimization::fetch_unroll_info (this function returns information - * about the number and size of interpreter frames which are equivalent to the frame which is being - * deoptimized) - * - *
  22. deallocate the unpack frame, restoring only results values. Other volatile registers will now - * be captured in the vframeArray as needed. - * - *
  23. deallocate the deoptimization frame - * - *
  24. in a loop using the information returned in the previous step push new interpreter frames - * (take care to propagate the return values through each new frame pushed) - * - *
  25. create a dummy "unpack_frame" and save the return values (O0, O1, F0) - * - *
  26. call the C routine: Deoptimization::unpack_frames (this function lays out values on the - * interpreter frame which was just created) - * - *
  27. deallocate the dummy unpack_frame - * - *
  28. ensure that all the return values are correctly set and then do a return to the interpreter - * entry point - * - *

    - * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet - * because we change the current stack layout and so the code is very sensitive to register - * allocation. - */ -public class UncommonTrapStub extends SnippetStub { - - public static final LocationIdentity STACK_BANG_LOCATION = NamedLocationIdentity.mutable("stack bang"); - - private final TargetDescription target; - - public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(UncommonTrapStub.class, "uncommonTrapHandler", providers, linkage); - this.target = target; - assert PreferGraalStubs.getValue(); - } - - @Override - public boolean preservesRegisters() { - return false; - } - - @Override - protected Object getConstantParameterValue(int index, String name) { - switch (index) { - case 0: - return providers.getRegisters().getThreadRegister(); - case 1: - return providers.getRegisters().getStackPointerRegister(); - default: - throw GraalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); - } - } - - /** - * Uncommon trap handler. - * - * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This - * routine captures the return values and returns a structure which describes the current frame - * size and the sizes of all replacement frames. The current frame is compiled code and may - * contain many inlined functions, each with their own JVM state. We pop the current frame, then - * push all the new frames. Then we call the C routine unpack_frames() to populate these frames. - * Finally unpack_frames() returns us the new target address. Notice that callee-save registers - * are BLOWN here; they have already been captured in the vframeArray at the time the return PC - * was patched. - */ - @Snippet - private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { - final Word thread = registerAsWord(threadRegister); - final long registerSaver = SaveAllRegistersNode.saveAllRegisters(); - - final int actionAndReason = readPendingDeoptimization(thread); - writePendingDeoptimization(thread, -1); - - final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason, deoptimizationUnpackUncommonTrap(INJECTED_VMCONFIG)); - - DeoptimizationStub.deoptimizationCommon(stackPointerRegister, thread, registerSaver, unrollBlock); - } - - /** - * Reads the value of the passed register as a Word. - */ - private static Word readRegister(Register register) { - return registerAsWord(register, false, false); - } - - /** - * Writes the value of the passed register. - * - * @param value value the register should be set to - */ - private static void writeRegister(Register register, Word value) { - writeRegisterAsWord(register, value); - } - - @Fold - static int stackShadowPages(@InjectedParameter GraalHotSpotVMConfig config) { - return config.useStackBanging ? config.stackShadowPages : 0; - } - - /** - * Returns the stack bias for the host architecture. - * - * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. - * - * @return stack bias - */ - @Deprecated - @Fold - static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) { - return config.stackBias; - } - - @Fold - static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; - } - - @Fold - static int deoptimizationUnrollBlockCallerAdjustmentOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockCallerAdjustmentOffset; - } - - @Fold - static int deoptimizationUnrollBlockNumberOfFramesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockNumberOfFramesOffset; - } - - @Fold - static int deoptimizationUnrollBlockTotalFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockTotalFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFramePcsOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFramePcsOffset; - } - - @Fold - static int deoptimizationUnrollBlockInitialInfoOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockInitialInfoOffset; - } - - @Fold - static int deoptimizationUnpackDeopt(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackDeopt; - } - - @Fold - static int deoptimizationUnpackUncommonTrap(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackUncommonTrap; - } - - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) - public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java index 5c8e0869c3d..8ad0ac79d37 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerInCallerNode.jumpToExceptionHandlerInCaller; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.checkExceptionNotNull; @@ -36,6 +37,7 @@ import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -43,8 +45,9 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.nodes.UnwindNode; -import org.graalvm.compiler.word.Pointer; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; +import org.graalvm.word.Pointer; import jdk.vm.ci.code.Register; @@ -54,8 +57,8 @@ import jdk.vm.ci.code.Register; */ public class UnwindExceptionToCallerStub extends SnippetStub { - public UnwindExceptionToCallerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("unwindExceptionToCaller", providers, linkage); + public UnwindExceptionToCallerStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("unwindExceptionToCaller", options, providers, linkage); } /** @@ -69,14 +72,17 @@ public class UnwindExceptionToCallerStub extends SnippetStub { @Override protected Object getConstantParameterValue(int index, String name) { - assert index == 2; - return providers.getRegisters().getThreadRegister(); + if (index == 2) { + return providers.getRegisters().getThreadRegister(); + } + assert index == 3; + return options; } @Snippet - private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister) { + private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { Pointer exceptionOop = Word.objectToTrackedPointer(exception); - if (logging()) { + if (logging(options)) { printf("unwinding exception %p (", exceptionOop.rawValue()); decipher(exceptionOop.rawValue()); printf(") at %p (", returnAddress.rawValue()); @@ -84,12 +90,12 @@ public class UnwindExceptionToCallerStub extends SnippetStub { printf(")\n"); } Word thread = registerAsWord(threadRegister); - checkNoExceptionInThread(thread, assertionsEnabled(null)); - checkExceptionNotNull(assertionsEnabled(null), exception); + checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG)); + checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception); Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread, returnAddress); - if (logging()) { + if (logging(options)) { printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue()); decipher(handlerInCallerPc.rawValue()); printf(")\n"); @@ -99,28 +105,23 @@ public class UnwindExceptionToCallerStub extends SnippetStub { } @Fold - static boolean logging() { - return StubOptions.TraceUnwindStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceUnwindStub.getValue(options); } /** - * Determines if either Java assertions are enabled for {@link UnwindExceptionToCallerStub} or - * if this is a HotSpot build where the ASSERT mechanism is enabled. - *

    - * This first check relies on the per-class assertion status which is why this method must be in - * this class. + * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build + * where the ASSERT mechanism is enabled. */ @Fold @SuppressWarnings("all") static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) { - boolean enabled = false; - assert enabled = true; - return enabled || cAssertionsEnabled(config); + return Assertions.ENABLED || cAssertionsEnabled(config); } public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class, Word.class); - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = StubForeignCallNode.class) public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java index ea11ef50079..dcd7442d462 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java @@ -28,14 +28,15 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; /** * Stub called via {@link HotSpotHostForeignCallsProvider#VERIFY_OOP}. */ public class VerifyOopStub extends SnippetStub { - public VerifyOopStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("verifyOop", providers, linkage); + public VerifyOopStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("verifyOop", options, providers, linkage); } @Snippet diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java index 0cad4f425eb..7efa5fa81de 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java @@ -27,10 +27,10 @@ import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.P import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.READ_KLASS_POINTER; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.TO_KLASS_POINTER; -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word.Opcode; import org.graalvm.compiler.word.Word.Operation; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; /** * Marker type for a metaspace pointer to a type. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java index 434471c08b7..280d1338b94 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java @@ -25,15 +25,15 @@ package org.graalvm.compiler.hotspot.word; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.FROM_POINTER; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.IS_NULL; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; -import org.graalvm.compiler.word.Pointer; -import org.graalvm.compiler.word.Signed; -import org.graalvm.compiler.word.Unsigned; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.Word.Opcode; import org.graalvm.compiler.word.Word.Operation; -import org.graalvm.compiler.word.WordBase; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.Signed; +import org.graalvm.word.Unsigned; +import org.graalvm.word.WordBase; /** * Marker type for a metaspace pointer. @@ -518,17 +518,6 @@ public abstract class MetaspacePointer { @Operation(opcode = Opcode.WRITE_POINTER) public abstract 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 - */ - @Operation(opcode = Opcode.INITIALIZE) - public abstract 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. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java index f00d0da5095..be27d05d013 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java @@ -26,7 +26,7 @@ import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.P 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.compiler.word.Pointer; +import org.graalvm.word.Pointer; /** * Marker type for a metaspace pointer to a method. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java index 725e6494bd5..ffd741ea670 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java @@ -81,7 +81,6 @@ import static org.graalvm.compiler.core.common.GraalOptions.SupportJsrBytecodes; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -93,9 +92,11 @@ import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.BytecodeSwitch; import org.graalvm.compiler.bytecode.BytecodeTableSwitch; import org.graalvm.compiler.bytecode.Bytecodes; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.CollectionsFactory; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.ExceptionHandler; @@ -157,7 +158,7 @@ public final class BciBlockMapping { public JSRData jsrData; public static class JSRData implements Cloneable { - public HashMap jsrAlternatives; + public EconomicMap jsrAlternatives; public JsrScope jsrScope = JsrScope.EMPTY_SCOPE; public BciBlock jsrSuccessor; public int jsrReturnBci; @@ -361,7 +362,7 @@ public final class BciBlockMapping { } } - public HashMap getJsrAlternatives() { + public EconomicMap getJsrAlternatives() { if (this.jsrData == null) { return null; } else { @@ -372,7 +373,7 @@ public final class BciBlockMapping { public void initJsrAlternatives() { JSRData data = this.getOrCreateJSRData(); if (data.jsrAlternatives == null) { - data.jsrAlternatives = new HashMap<>(); + data.jsrAlternatives = EconomicMap.create(Equivalence.DEFAULT); } } @@ -415,7 +416,7 @@ public final class BciBlockMapping { public static class ExceptionDispatchBlock extends BciBlock { - private HashMap exceptionDispatch = new HashMap<>(); + private EconomicMap exceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); public ExceptionHandler handler; public int deoptBci; @@ -436,8 +437,6 @@ public final class BciBlockMapping { private static final int LOOP_HEADER_INITIAL_CAPACITY = 4; private int blocksNotYetAssignedId; - public int returnCount; - private int returnBci; /** * Creates a new BlockMap instance from {@code code}. @@ -451,20 +450,16 @@ public final class BciBlockMapping { return this.blocks; } - public int getReturnCount() { - return this.returnCount; - } - /** * Builds the block map and conservative CFG and numbers blocks. */ - public void build(BytecodeStream stream) { + public void build(BytecodeStream stream, OptionValues options) { int codeSize = code.getCodeSize(); BciBlock[] blockMap = new BciBlock[codeSize]; makeExceptionEntries(blockMap); iterateOverBytecodes(blockMap, stream); if (hasJsrBytecodes) { - if (!SupportJsrBytecodes.getValue()) { + if (!SupportJsrBytecodes.getValue(options)) { throw new JsrNotSupportedBailout("jsr/ret parsing disabled"); } createJsrAlternatives(blockMap, blockMap[0]); @@ -532,9 +527,7 @@ public final class BciBlockMapping { case DRETURN: // fall through case ARETURN: // fall through case RETURN: { - returnCount++; current = null; - returnBci = bci; break; } case ATHROW: { @@ -753,7 +746,14 @@ public final class BciBlockMapping { } } - private HashMap initialExceptionDispatch = CollectionsFactory.newMap(); + private EconomicMap initialExceptionDispatch; + + private EconomicMap getInitialExceptionDispatch() { + if (initialExceptionDispatch == null) { + initialExceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); + } + return initialExceptionDispatch; + } private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) { ExceptionDispatchBlock lastHandler = null; @@ -767,7 +767,7 @@ public final class BciBlockMapping { lastHandler = null; } - HashMap exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : initialExceptionDispatch; + EconomicMap exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : getInitialExceptionDispatch(); ExceptionDispatchBlock curHandler = exceptionDispatch.get(h); if (curHandler == null) { curHandler = new ExceptionDispatchBlock(); @@ -824,7 +824,7 @@ public final class BciBlockMapping { // Purge null entries for unreached blocks and sort blocks such that loop bodies are always // consecutively in the array. - int blockCount = maxBlocks - blocksNotYetAssignedId + 2; + int blockCount = maxBlocks - blocksNotYetAssignedId + 1; BciBlock[] newBlocks = new BciBlock[blockCount]; int next = 0; for (int i = 0; i < blocks.length; ++i) { @@ -837,13 +837,7 @@ public final class BciBlockMapping { } } } - - // Add return block. - BciBlock returnBlock = new BciBlock(); - returnBlock.startBci = returnBci; - returnBlock.endBci = returnBci; - returnBlock.setId(newBlocks.length - 2); - newBlocks[newBlocks.length - 2] = returnBlock; + assert next == newBlocks.length - 1; // Add unwind block. ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(); @@ -1040,11 +1034,11 @@ public final class BciBlockMapping { return loops; } - public static BciBlockMapping create(BytecodeStream stream, Bytecode code) { + public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options) { BciBlockMapping map = new BciBlockMapping(code); - map.build(stream); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); + map.build(stream, options); + if (Debug.isDumpEnabled(Debug.INFO_LEVEL)) { + Debug.dump(Debug.INFO_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); } return map; @@ -1058,10 +1052,6 @@ public final class BciBlockMapping { return startBlock; } - public BciBlock getReturnBlock() { - return blocks[blocks.length - 2]; - } - public ExceptionDispatchBlock getUnwindBlock() { return (ExceptionDispatchBlock) blocks[blocks.length - 1]; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 7ace642641e..da2cdfc5afe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -22,6 +22,18 @@ */ package org.graalvm.compiler.java; +import static java.lang.String.format; +import static java.lang.reflect.Modifier.STATIC; +import static java.lang.reflect.Modifier.SYNCHRONIZED; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; +import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; +import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; +import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; +import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; +import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; +import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE; import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL; @@ -227,39 +239,32 @@ import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH; import static org.graalvm.compiler.bytecode.Bytecodes.nameOf; import static org.graalvm.compiler.core.common.GraalOptions.DeoptALot; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import static org.graalvm.compiler.core.common.GraalOptions.PrintProfilingInformation; import static org.graalvm.compiler.core.common.GraalOptions.ResolveClassBeforeStaticInvoke; +import static org.graalvm.compiler.core.common.GraalOptions.StressExplicitExceptionCode; import static org.graalvm.compiler.core.common.GraalOptions.StressInvokeWithExceptionNode; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull; import static org.graalvm.compiler.debug.GraalError.guarantee; import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere; -import static org.graalvm.compiler.java.BytecodeParserOptions.DumpDuringGraphBuilding; +import static org.graalvm.compiler.java.BytecodeParserOptions.DumpWithInfopoints; +import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing; +import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins; import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING; import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull; -import static java.lang.String.format; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; -import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; -import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; -import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; -import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; -import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; -import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; -import java.lang.ref.Reference; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Formatter; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.bytecode.BytecodeLookupSwitch; @@ -268,21 +273,20 @@ import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.BytecodeSwitch; import org.graalvm.compiler.bytecode.BytecodeTableSwitch; import org.graalvm.compiler.bytecode.Bytecodes; +import org.graalvm.compiler.bytecode.Bytes; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; -import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; 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.core.common.type.TypeReference; import org.graalvm.compiler.core.common.util.Util; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.debug.DebugCloseable; @@ -296,7 +300,6 @@ import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.java.BciBlockMapping.ExceptionDispatchBlock; -import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.BeginNode; @@ -361,12 +364,8 @@ import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; -import org.graalvm.compiler.nodes.debug.instrumentation.InstrumentationBeginNode; import org.graalvm.compiler.nodes.extended.AnchoringNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; -import org.graalvm.compiler.nodes.extended.GuardedNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; @@ -402,7 +401,12 @@ import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.util.ValueMergeUtil; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodeFrame; @@ -426,6 +430,7 @@ import jdk.vm.ci.meta.RawConstant; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.TriState; /** @@ -460,6 +465,7 @@ public class BytecodeParser implements GraphBuilderContext { FrameState stateBefore; final Mark mark; final BytecodeParser parser; + List returnDataList; /** * Creates a scope for root parsing an intrinsic. @@ -501,46 +507,50 @@ public class BytecodeParser implements GraphBuilderContext { * added to the graph while parsing/inlining the intrinsic for which this object exists. */ private void processPlaceholderFrameStates(IntrinsicContext intrinsic) { - FrameState stateAfterReturn = null; StructuredGraph graph = parser.getGraph(); for (Node node : graph.getNewNodes(mark)) { if (node instanceof FrameState) { FrameState frameState = (FrameState) node; if (BytecodeFrame.isPlaceholderBci(frameState.bci)) { if (frameState.bci == BytecodeFrame.AFTER_BCI) { - FrameStateBuilder frameStateBuilder = parser.frameState; - if (frameState.stackSize() != 0) { - assert frameState.usages().count() == 1; - ValueNode returnVal = frameState.stackAt(0); - assert returnVal == frameState.usages().first(); + if (parser.getInvokeReturnType() == null) { + // A frame state in a root compiled intrinsic. + assert intrinsic.isCompilationRoot(); + FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); + frameState.replaceAndDelete(newFrameState); + } else { + JavaKind returnKind = parser.getInvokeReturnType().getJavaKind(); + FrameStateBuilder frameStateBuilder = parser.frameState; + assert !frameState.rethrowException(); + if (frameState.stackSize() != 0) { + ValueNode returnVal = frameState.stackAt(0); + if (!ReturnToCallerData.containsReturnValue(returnDataList, returnVal)) { + throw new GraalError("AFTER_BCI frame state within an intrinsic has a non-return value on the stack: %s", returnVal); + } - if (parser.currentInvokeReturnType == null) { - assert intrinsic.isCompilationRoot(); - FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); - frameState.replaceAndDelete(newFrameState); - } else { - /* - * Swap the top-of-stack value with the side-effect return value - * using the frame state. - */ - JavaKind returnKind = parser.currentInvokeReturnType.getJavaKind(); + // Swap the top-of-stack value with the return value ValueNode tos = frameStateBuilder.pop(returnKind); assert tos.getStackKind() == returnVal.getStackKind(); FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), parser.getNonIntrinsicAncestor(), false, new JavaKind[]{returnKind}, new ValueNode[]{returnVal}); frameState.replaceAndDelete(newFrameState); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); frameStateBuilder.push(returnKind, tos); + } else if (returnKind != JavaKind.Void) { + // If the intrinsic returns a non-void value, then any frame + // state with an empty stack is invalid as it cannot + // be used to deoptimize to just after the call returns. + // These invalid frame states are expected to be removed + // by later compilation stages. + FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); + frameState.replaceAndDelete(newFrameState); + } else { + // An intrinsic for a void method. + FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); + frameState.replaceAndDelete(newFrameState); } - } else { - if (stateAfterReturn == null) { - if (intrinsic != null) { - assert intrinsic.isCompilationRoot(); - stateAfterReturn = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); - } else { - stateAfterReturn = frameStateBuilder.create(parser.stream.nextBCI(), null); - } - } - frameState.replaceAndDelete(stateAfterReturn); } } else if (frameState.bci == BytecodeFrame.BEFORE_BCI) { if (stateBefore == null) { @@ -549,6 +559,24 @@ public class BytecodeParser implements GraphBuilderContext { if (stateBefore != frameState) { frameState.replaceAndDelete(stateBefore); } + } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { + // This is a frame state for the entry point to an exception + // dispatcher in an intrinsic. For example, the invoke denoting + // a partial intrinsic exit will have an edge to such a + // dispatcher if the profile for the original invoke being + // intrinsified indicates an exception was seen. As per JVM + // bytecode semantics, the interpreter expects a single + // value on the stack on entry to an exception handler, + // namely the exception object. + assert frameState.rethrowException(); + ExceptionObjectNode exceptionObject = (ExceptionObjectNode) frameState.stackAt(0); + FrameStateBuilder dispatchState = parser.frameState.copy(); + dispatchState.clearStack(); + dispatchState.push(JavaKind.Object, exceptionObject); + dispatchState.setRethrowException(true); + FrameState newFrameState = dispatchState.create(parser.bci(), exceptionObject); + frameState.replaceAndDelete(newFrameState); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); } else { assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI; } @@ -580,8 +608,28 @@ public class BytecodeParser implements GraphBuilderContext { } } + protected static class ReturnToCallerData { + protected final ValueNode returnValue; + protected final FixedWithNextNode beforeReturnNode; + + protected ReturnToCallerData(ValueNode returnValue, FixedWithNextNode beforeReturnNode) { + this.returnValue = returnValue; + this.beforeReturnNode = beforeReturnNode; + } + + static boolean containsReturnValue(List list, ValueNode value) { + for (ReturnToCallerData e : list) { + if (e.returnValue == value) { + return true; + } + } + return false; + } + } + private final GraphBuilderPhase.Instance graphBuilderInstance; protected final StructuredGraph graph; + protected final OptionValues options; private BciBlockMapping blockMap; private LocalLiveness liveness; @@ -594,8 +642,7 @@ public class BytecodeParser implements GraphBuilderContext { private ValueNode methodSynchronizedObject; - private ValueNode returnValue; - private FixedWithNextNode beforeReturnNode; + private List returnDataList; private ValueNode unwindValue; private FixedWithNextNode beforeUnwindNode; @@ -606,8 +653,6 @@ public class BytecodeParser implements GraphBuilderContext { private FixedWithNextNode[] firstInstructionArray; private FrameStateBuilder[] entryStateArray; - private int lastBCI; // BCI of lastInstr. This field is for resolving instrumentation target. - private boolean finalBarrierRequired; private ValueNode originalReceiver; @@ -618,6 +663,7 @@ public class BytecodeParser implements GraphBuilderContext { this.method = code.getMethod(); this.graphBuilderInstance = graphBuilderInstance; this.graph = graph; + this.options = graph.getOptions(); this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig; this.optimisticOpts = graphBuilderInstance.optimisticOpts; this.metaAccess = graphBuilderInstance.metaAccess; @@ -630,7 +676,6 @@ public class BytecodeParser implements GraphBuilderContext { this.intrinsicContext = intrinsicContext; this.entryBCI = entryBCI; this.parent = parent; - this.lastBCI = -1; assert code.getCode() != null : "method must contain bytecodes: " + method; @@ -644,14 +689,6 @@ public class BytecodeParser implements GraphBuilderContext { return graphBuilderInstance; } - public ValueNode getReturnValue() { - return returnValue; - } - - public FixedWithNextNode getBeforeReturnNode() { - return this.beforeReturnNode; - } - public ValueNode getUnwindValue() { return unwindValue; } @@ -675,7 +712,7 @@ public class BytecodeParser implements GraphBuilderContext { @SuppressWarnings("try") protected void build(FixedWithNextNode startInstruction, FrameStateBuilder startFrameState) { - if (PrintProfilingInformation.getValue() && profilingInfo != null) { + if (PrintProfilingInformation.getValue(options) && profilingInfo != null) { TTY.println("Profiling info for " + method.format("%H.%n(%p)")); TTY.println(Util.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), " ")); } @@ -688,7 +725,7 @@ public class BytecodeParser implements GraphBuilderContext { } // compute the block map, setup exception handlers and get the entrypoint(s) - BciBlockMapping newMapping = BciBlockMapping.create(stream, code); + BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options); this.blockMap = newMapping; this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()]; this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()]; @@ -741,6 +778,8 @@ public class BytecodeParser implements GraphBuilderContext { } if (method.isSynchronized()) { + finishPrepare(lastInstr, BytecodeFrame.BEFORE_BCI); + // add a monitor enter to the start block methodSynchronizedObject = synchronizedObject(frameState, method); frameState.clearNonLiveLocals(startBlock, liveness, true); @@ -754,7 +793,7 @@ public class BytecodeParser implements GraphBuilderContext { profilingPlugin.profileInvoke(this, method, stateBefore); } - finishPrepare(lastInstr); + finishPrepare(lastInstr, 0); genInfoPointNode(InfopointReason.METHOD_START, null); @@ -770,10 +809,6 @@ public class BytecodeParser implements GraphBuilderContext { for (BciBlock block : blocks) { processBlock(block); } - - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL) && DumpDuringGraphBuilding.getValue() && this.beforeReturnNode != startInstruction) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Bytecodes parsed: %s.%s", method.getDeclaringClass().getUnqualifiedName(), method.getName()); - } } } @@ -800,11 +835,12 @@ public class BytecodeParser implements GraphBuilderContext { } /** - * Hook for subclasses to modify the graph start instruction or append new instructions to it. + * Hook for subclasses to modify synthetic code (start nodes and unwind nodes). * - * @param startInstr the start instruction of the graph + * @param instruction the current last instruction + * @param bci the current bci */ - protected void finishPrepare(FixedWithNextNode startInstr) { + protected void finishPrepare(FixedWithNextNode instruction, int bci) { } protected void cleanupFinalGraph() { @@ -823,46 +859,13 @@ public class BytecodeParser implements GraphBuilderContext { Node predecessor = beginNode.predecessor(); if (predecessor instanceof ControlSplitNode) { // The begin node is necessary. - } else { - if (beginNode.hasUsages()) { - reanchorGuardedNodes(beginNode); - } + } else if (!beginNode.hasUsages()) { GraphUtil.unlinkFixedNode(beginNode); beginNode.safeDelete(); } } } - /** - * Removes {@link GuardedNode}s from {@code beginNode}'s usages and re-attaches them to an - * appropriate preceeding {@link GuardingNode}. - */ - protected void reanchorGuardedNodes(BeginNode beginNode) { - // Find the new guarding node - GuardingNode guarding = null; - Node pred = beginNode.predecessor(); - while (pred != null) { - if (pred instanceof BeginNode) { - if (pred.predecessor() instanceof ControlSplitNode) { - guarding = (GuardingNode) pred; - break; - } - } else if (pred.getNodeClass().getAllowedUsageTypes().contains(InputType.Guard)) { - guarding = (GuardingNode) pred; - break; - } - pred = pred.predecessor(); - } - - // Reset the guard for all of beginNode's usages - for (Node usage : beginNode.usages().snapshot()) { - GuardedNode guarded = (GuardedNode) usage; - assert guarded.getGuard() == beginNode; - guarded.setGuard(guarding); - } - assert beginNode.hasNoUsages() : beginNode; - } - /** * Creates the frame state after the start node of a graph for an {@link IntrinsicContext * intrinsic} that is the parse root (either for root compiling or for post-parse inlining). @@ -922,7 +925,7 @@ public class BytecodeParser implements GraphBuilderContext { */ protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { assert !graphBuilderConfig.eagerResolving(); - append(new FixedGuardNode(graph.unique(IsNullNode.create(object)), Unresolved, InvalidateRecompile)); + append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), Unresolved, InvalidateRecompile)); frameState.push(JavaKind.Object, appendConstant(JavaConstant.NULL_POINTER)); } @@ -934,7 +937,7 @@ public class BytecodeParser implements GraphBuilderContext { assert !graphBuilderConfig.eagerResolving(); AbstractBeginNode successor = graph.add(new BeginNode()); DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - append(new IfNode(graph.unique(IsNullNode.create(object)), successor, deopt, 1)); + append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), successor, deopt, 1)); lastInstr = successor; frameState.push(JavaKind.Int, appendConstant(JavaConstant.INT_0)); } @@ -1092,15 +1095,15 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genNegateOp(ValueNode x) { - return (new NegateNode(x)); + return NegateNode.create(x); } protected ValueNode genLeftShift(ValueNode x, ValueNode y) { - return new LeftShiftNode(x, y); + return LeftShiftNode.create(x, y); } protected ValueNode genRightShift(ValueNode x, ValueNode y) { - return new RightShiftNode(x, y); + return RightShiftNode.create(x, y); } protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) { @@ -1120,7 +1123,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) { - return NormalizeCompareNode.create(x, y, isUnorderedLess, constantReflection); + return NormalizeCompareNode.create(x, y, isUnorderedLess, JavaKind.Int, constantReflection); } protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) { @@ -1151,15 +1154,15 @@ public class BytecodeParser implements GraphBuilderContext { } protected LogicNode genObjectEquals(ValueNode x, ValueNode y) { - return ObjectEqualsNode.create(x, y, constantReflection); + return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y); } protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) { - return IntegerEqualsNode.create(x, y, constantReflection); + return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y); } protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) { - return IntegerLessThanNode.create(x, y, constantReflection); + return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y); } protected ValueNode genUnique(ValueNode x) { @@ -1178,8 +1181,8 @@ public class BytecodeParser implements GraphBuilderContext { genInfoPointNode(InfopointReason.BYTECODE_POSITION, null); ValueNode exception = frameState.pop(JavaKind.Object); - FixedGuardNode nullCheck = append(new FixedGuardNode(graph.unique(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); - PiNode nonNullException = graph.unique(new PiNode(exception, exception.stamp().join(objectNonNull()), nullCheck)); + FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); + ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck)); lastInstr.setNext(handleException(nonNullException, bci())); } @@ -1204,7 +1207,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genConditional(ValueNode x) { - return new ConditionalNode((LogicNode) x); + return ConditionalNode.create((LogicNode) x); } protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { @@ -1222,9 +1225,11 @@ public class BytecodeParser implements GraphBuilderContext { protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) { StampPair stamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, field.getType(), false); if (stamp == null) { - return LoadFieldNode.create(this.graph.getAssumptions(), receiver, field); + return LoadFieldNode.create(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(), + getAssumptions(), receiver, field, false, false); } else { - return LoadFieldNode.createOverrideStamp(stamp, receiver, field); + return LoadFieldNode.createOverrideStamp(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(), + stamp, receiver, field, false, false); } } @@ -1234,19 +1239,20 @@ public class BytecodeParser implements GraphBuilderContext { } BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class)); AbstractBeginNode falseSucc = graph.add(new BeginNode()); - PiNode nonNullReceiver = graph.unique(new PiNode(receiver, receiver.stamp().join(objectNonNull()), falseSucc)); - append(new IfNode(graph.unique(IsNullNode.create(receiver)), exception, falseSucc, 0.01)); + ValueNode nonNullReceiver = graph.addOrUnique(PiNode.create(receiver, objectNonNull(), falseSucc)); + append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY)); lastInstr = falseSucc; exception.setStateAfter(createFrameState(bci(), exception)); exception.setNext(handleException(exception, bci())); + EXPLICIT_EXCEPTIONS.increment(); return nonNullReceiver; } protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) { AbstractBeginNode trueSucc = graph.add(new BeginNode()); BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); - append(new IfNode(graph.unique(IntegerBelowNode.create(index, length, constantReflection)), trueSucc, exception, 0.99)); + append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY)); lastInstr = trueSucc; exception.setStateAfter(createFrameState(bci(), exception)); @@ -1283,7 +1289,7 @@ public class BytecodeParser implements GraphBuilderContext { if (callTargetIsResolved(target)) { ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); - if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue()) { + if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue(options)) { handleUnresolvedInvoke(target, InvokeKind.Static); } else { ValueNode classInit = null; @@ -1361,8 +1367,19 @@ public class BytecodeParser implements GraphBuilderContext { } } - private InvokeKind currentInvokeKind; - private JavaType currentInvokeReturnType; + static class CurrentInvoke { + final ValueNode[] args; + final InvokeKind kind; + final JavaType returnType; + + CurrentInvoke(ValueNode[] args, InvokeKind kind, JavaType returnType) { + this.args = args; + this.kind = kind; + this.returnType = returnType; + } + } + + private CurrentInvoke currentInvoke; protected FrameStateBuilder frameState; protected BciBlock currentBlock; protected final BytecodeStream stream; @@ -1381,12 +1398,12 @@ public class BytecodeParser implements GraphBuilderContext { @Override public InvokeKind getInvokeKind() { - return currentInvokeKind; + return currentInvoke == null ? null : currentInvoke.kind; } @Override public JavaType getInvokeReturnType() { - return currentInvokeReturnType; + return currentInvoke == null ? null : currentInvoke.returnType; } private boolean forceInliningEverything; @@ -1402,6 +1419,13 @@ public class BytecodeParser implements GraphBuilderContext { } } + @Override + public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) { + BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor(); + boolean withExceptionEdge = intrinsicCallSiteParser == null ? !omitInvokeExceptionEdge(null) : !intrinsicCallSiteParser.omitInvokeExceptionEdge(null); + createNonInlinedInvoke(withExceptionEdge, bci(), callTarget, resultType); + } + private Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) { ResolvedJavaMethod targetMethod = initialTargetMethod; InvokeKind invokeKind = initialInvokeKind; @@ -1415,7 +1439,7 @@ public class BytecodeParser implements GraphBuilderContext { } JavaKind resultType = targetMethod.getSignature().getReturnKind(); - if (DeoptALot.getValue()) { + if (!parsingIntrinsic() && DeoptALot.getValue(options)) { append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph)); return null; @@ -1426,28 +1450,27 @@ public class BytecodeParser implements GraphBuilderContext { returnType = returnType.resolve(targetMethod.getDeclaringClass()); } if (invokeKind.hasReceiver()) { - args[0] = emitExplicitExceptions(args[0], null); - - if (args[0].isNullConstant()) { - append(new DeoptimizeNode(InvalidateRecompile, NullCheckException)); - return null; - } + args[0] = emitExplicitExceptions(args[0]); } InlineInfo inlineInfo = null; try { - currentInvokeReturnType = returnType; - currentInvokeKind = invokeKind; + currentInvoke = new CurrentInvoke(args, invokeKind, returnType); if (tryNodePluginForInvocation(args, targetMethod)) { - if (TraceParserPlugins.getValue()) { + if (TraceParserPlugins.getValue(options)) { traceWithContext("used node plugin for %s", targetMethod.format("%h.%n(%p)")); } return null; } - if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue() && !GeneratePIC.getValue())) { + if (invokeKind.hasReceiver() && args[0].isNullConstant()) { + append(new DeoptimizeNode(InvalidateRecompile, NullCheckException)); + return null; + } + + if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) { if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) { - if (TraceParserPlugins.getValue()) { + if (TraceParserPlugins.getValue(options)) { traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)")); } return null; @@ -1461,36 +1484,99 @@ public class BytecodeParser implements GraphBuilderContext { } } } finally { - currentInvokeReturnType = null; - currentInvokeKind = null; + currentInvoke = null; } - JavaTypeProfile profile = null; - if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints()) { - profile = profilingInfo.getTypeProfile(bci()); + int invokeBci = bci(); + JavaTypeProfile profile = getProfileForInvoke(invokeKind); + boolean withExceptionEdge = !omitInvokeExceptionEdge(inlineInfo); + boolean partialIntrinsicExit = false; + if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) { + partialIntrinsicExit = true; + ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod(); + BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor(); + if (intrinsicCallSiteParser != null) { + // When exiting a partial intrinsic, the invoke to the original + // must use the same context as the call to the intrinsic. + invokeBci = intrinsicCallSiteParser.bci(); + profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind); + withExceptionEdge = !intrinsicCallSiteParser.omitInvokeExceptionEdge(inlineInfo); + } else { + // We are parsing the intrinsic for the root compilation or for inlining, + // This call is a partial intrinsic exit, and we do not have profile information + // for this callsite. We also have to assume that the call needs an exception + // edge. Finally, we know that this intrinsic is parsed for late inlining, + // so the bci must be set to unknown, so that the inliner patches it later. + assert intrinsicContext.isPostParseInlined(); + invokeBci = BytecodeFrame.UNKNOWN_BCI; + profile = null; + withExceptionEdge = graph.method().getAnnotation(Snippet.class) == null; + } + + if (originalMethod.isStatic()) { + invokeKind = InvokeKind.Static; + } else { + // The original call to the intrinsic must have been devirtualized + // otherwise we wouldn't be here. + invokeKind = InvokeKind.Special; + } + Signature sig = originalMethod.getSignature(); + returnType = sig.getReturnType(method.getDeclaringClass()); + resultType = sig.getReturnKind(); + assert checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args); + targetMethod = originalMethod; } - return createNonInlinedInvoke(args, targetMethod, invokeKind, resultType, returnType, inlineInfo, profile); + Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile); + 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 + // the intrinsic graph, prevent this invoke from being inlined. + invoke.setUseForInlining(false); + } + return invoke; } - protected Invoke createNonInlinedInvoke(ValueNode[] args, ResolvedJavaMethod targetMethod, InvokeKind invokeKind, - JavaKind resultType, JavaType returnType, InlineInfo inlineInfo, JavaTypeProfile profile) { + protected JavaTypeProfile getProfileForInvoke(InvokeKind invokeKind) { + if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { + return profilingInfo.getTypeProfile(bci()); + } + return null; + } + + /** + * A partial intrinsic exits by (effectively) calling the intrinsified method. This call must + * use exactly the arguments to the call being intrinsified. + * + * @param originalArgs arguments of original call to intrinsified method + * @param recursiveArgs arguments of recursive call to intrinsified method + */ + private static boolean checkPartialIntrinsicExit(ValueNode[] originalArgs, ValueNode[] recursiveArgs) { + if (originalArgs != null) { + for (int i = 0; i < originalArgs.length; i++) { + ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]); + ValueNode icArg = GraphUtil.unproxify(originalArgs[i]); + assert arg == icArg : String.format("argument %d of call denoting partial intrinsic exit should be %s, not %s", i, icArg, arg); + } + } else { + for (int i = 0; i < recursiveArgs.length; i++) { + ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]); + assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s", i, + ParameterNode.class.getSimpleName(), i, arg); + } + } + return true; + } + + protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod, + InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) { StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false); if (returnStamp == null) { returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false); } - MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnStamp, profile)); - - Invoke invoke; - if (omitInvokeExceptionEdge(callTarget, inlineInfo)) { - invoke = createInvoke(callTarget, resultType); - } else { - invoke = createInvokeWithException(callTarget, resultType); - AbstractBeginNode beginNode = graph.add(new KillingBeginNode(LocationIdentity.any())); - invoke.setNext(beginNode); - lastInstr = beginNode; - } + MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile)); + Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, callTarget, resultType); for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { plugin.notifyNotInlined(this, targetMethod, invoke); @@ -1499,26 +1585,48 @@ public class BytecodeParser implements GraphBuilderContext { return invoke; } + protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) { + if (!withExceptionEdge) { + return createInvoke(invokeBci, callTarget, resultType); + } else { + Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType); + AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any())); + invoke.setNext(beginNode); + lastInstr = beginNode; + return invoke; + } + } + /** * If the method returns true, the invocation of the given {@link MethodCallTargetNode call * target} does not need an exception edge. - * - * @param callTarget The call target. */ - protected boolean omitInvokeExceptionEdge(MethodCallTargetNode callTarget, InlineInfo lastInlineInfo) { + protected boolean omitInvokeExceptionEdge(InlineInfo lastInlineInfo) { if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) { return false; } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) { return true; } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) { return false; + } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) { + return false; } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) { return true; } else { assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile; // be conservative if information was not recorded (could result in endless // recompiles otherwise) - return (!StressInvokeWithExceptionNode.getValue() && optimisticOpts.useExceptionProbability() && profilingInfo != null && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE); + if (!StressInvokeWithExceptionNode.getValue(options)) { + if (optimisticOpts.useExceptionProbability(getOptions())) { + if (profilingInfo != null) { + TriState exceptionSeen = profilingInfo.getExceptionSeen(bci()); + if (exceptionSeen == TriState.FALSE) { + return true; + } + } + } + } + return false; } } @@ -1537,7 +1645,7 @@ public class BytecodeParser implements GraphBuilderContext { final Mark mark; InvocationPluginAssertions(InvocationPlugin plugin, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) { - guarantee(assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName()); + guarantee(Assertions.ENABLED, "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName()); this.plugin = plugin; this.targetMethod = targetMethod; this.args = args; @@ -1622,7 +1730,7 @@ public class BytecodeParser implements GraphBuilderContext { receiverType = targetMethod.getDeclaringClass(); } ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass()); - if (resolvedMethod == null || resolvedMethod == targetMethod) { + if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) { assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass()); Mark mark = graph.getMark(); FixedWithNextNode currentLastInstr = lastInstr; @@ -1631,10 +1739,10 @@ public class BytecodeParser implements GraphBuilderContext { LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver)); LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub)); ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess())); - LogicNode compare = graph.unique(CompareNode.createCompareNode(Condition.EQ, actual, expected, constantReflection)); + LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected)); JavaTypeProfile profile = null; - if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints()) { + if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { profile = profilingInfo.getTypeProfile(bci()); if (profile != null) { JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod); @@ -1655,7 +1763,7 @@ public class BytecodeParser implements GraphBuilderContext { AbstractBeginNode intrinsicBranch = graph.add(new BeginNode()); AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode()); - append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, 0.01)); + append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY)); lastInstr = intrinsicBranch; return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile); } else { @@ -1697,15 +1805,15 @@ public class BytecodeParser implements GraphBuilderContext { /** * Performs any action required after execution of an invocation plugin. This includes - * {@linkplain InvocationPluginAssertions#check(boolean) checking} invocation plugin invariants - * as well as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if + * {@linkplain InvocationPluginAssertions#check checking} invocation plugin invariants as well + * as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if * {@code guard != null}. */ - protected void afterInvocationPluginExecution(boolean pluginResult, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard, + protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard, InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) { - assert assertions.check(pluginResult); + assert assertions.check(pluginHandledInvoke); if (intrinsicGuard != null) { - if (pluginResult) { + if (pluginHandledInvoke) { if (intrinsicGuard.nonIntrinsicBranch != null) { // Intrinsic emitted: emit a virtual call to the target method and // merge it with the intrinsic branch @@ -1720,7 +1828,7 @@ public class BytecodeParser implements GraphBuilderContext { } lastInstr = intrinsicGuard.nonIntrinsicBranch; - createNonInlinedInvoke(args, targetMethod, invokeKind, resultType, returnType, null, intrinsicGuard.profile); + createNonInlinedInvoke(omitInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile); EndNode nonIntrinsicEnd = append(new EndNode()); AbstractMergeNode mergeNode = graph.add(new MergeNode()); @@ -1769,7 +1877,7 @@ public class BytecodeParser implements GraphBuilderContext { } } - InvocationPluginAssertions assertions = assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; + InvocationPluginAssertions assertions = Assertions.ENABLED ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; if (plugin.execute(this, targetMethod, pluginReceiver, args)) { afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType); return true; @@ -1817,14 +1925,53 @@ public class BytecodeParser implements GraphBuilderContext { if (inline(targetMethod, inlineInfo.getMethodToInline(), inlineInfo.getIntrinsicBytecodeProvider(), args)) { return SUCCESSFULLY_INLINED; } + inlineInfo = null; } /* Do not inline, and do not ask the remaining plugins. */ return inlineInfo; } } + + // There was no inline plugin with a definite answer to whether or not + // to inline. If we're parsing an intrinsic, then we need to enforce the + // invariant here that methods are always force inlined in intrinsics/snippets. + if (parsingIntrinsic()) { + if (inline(targetMethod, targetMethod, this.bytecodeProvider, args)) { + return SUCCESSFULLY_INLINED; + } + } return null; } + private static final int ACCESSOR_BYTECODE_LENGTH = 5; + + /** + * Tries to inline {@code targetMethod} if it is an instance field accessor. This avoids the + * overhead of creating and using a nested {@link BytecodeParser} object. + */ + private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) { + byte[] bytecode = targetMethod.getCode(); + if (bytecode.length == ACCESSOR_BYTECODE_LENGTH && + Bytes.beU1(bytecode, 0) == ALOAD_0 && + Bytes.beU1(bytecode, 1) == GETFIELD) { + int b4 = Bytes.beU1(bytecode, 4); + if (b4 >= IRETURN && b4 <= ARETURN) { + int cpi = Bytes.beU2(bytecode, 2); + JavaField field = targetMethod.getConstantPool().lookupField(cpi, targetMethod, GETFIELD); + if (field instanceof ResolvedJavaField) { + ValueNode receiver = invocationPluginReceiver.init(targetMethod, args).get(); + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + genGetField(resolvedField, receiver); + notifyBeforeInline(targetMethod); + printInlining(targetMethod, targetMethod, true, "inline accessor method (bytecode parsing)"); + notifyAfterInline(targetMethod); + return true; + } + } + } + return false; + } + @Override public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) { if (receiver != null) { @@ -1836,14 +1983,15 @@ public class BytecodeParser implements GraphBuilderContext { } private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) { - if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) { - if (targetMethod.equals(inlinedMethod)) { - traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)")); - } else { - traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)")); - } - } 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 @@ -1854,16 +2002,23 @@ public class BytecodeParser implements GraphBuilderContext { printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)"); return true; } else { - // Otherwise inline the original method. Any frame state created - // during the inlining will exclude frame(s) in the - // intrinsic method (see HIRFrameStateBuilder.create(int bci)). if (intrinsic.getOriginalMethod().isNative()) { printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)"); return false; } - printInlining(targetMethod, inlinedMethod, true, "inline intrinsic (bytecode parsing)"); - parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null); - return true; + 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); + return true; + } else { + printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)"); + return false; + } } } else { boolean isIntrinsic = intrinsicBytecodeProvider != null; @@ -1872,14 +2027,10 @@ public class BytecodeParser implements GraphBuilderContext { intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING); } if (inlinedMethod.hasBytecodes()) { - for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { - plugin.notifyBeforeInline(inlinedMethod); - } + notifyBeforeInline(inlinedMethod); printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)"); parseAndInlineCallee(inlinedMethod, args, intrinsic); - for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { - plugin.notifyAfterInline(inlinedMethod); - } + notifyAfterInline(inlinedMethod); } else { printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)"); return false; @@ -1888,8 +2039,37 @@ public class BytecodeParser implements GraphBuilderContext { return true; } + protected void notifyBeforeInline(ResolvedJavaMethod inlinedMethod) { + for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { + plugin.notifyBeforeInline(inlinedMethod); + } + } + + protected void notifyAfterInline(ResolvedJavaMethod inlinedMethod) { + for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { + plugin.notifyAfterInline(inlinedMethod); + } + } + + /** + * Determines if a partial intrinsic exit (i.e., a call to the original method within an + * intrinsic) can be inlined. + */ + protected boolean canInlinePartialIntrinsicExit() { + return true; + } + private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean success, String msg) { - if (GraalOptions.HotSpotPrintInlining.getValue()) { + if (success) { + if (TraceInlineDuringParsing.getValue(options) || TraceParserPlugins.getValue(options)) { + if (targetMethod.equals(inlinedMethod)) { + traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)")); + } else { + traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)")); + } + } + } + if (HotSpotPrintInlining.getValue(options)) { if (targetMethod.equals(inlinedMethod)) { Util.printInlining(inlinedMethod, bci(), getDepth(), success, "%s", msg); } else { @@ -1914,8 +2094,12 @@ public class BytecodeParser implements GraphBuilderContext { protected void traceWithContext(String format, Object... args) { StackTraceElement where = code.asStackTraceElement(bci()); - TTY.println(format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), - format(format, args))); + String s = format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), + format(format, args)); + if (s.equals("decrypt (CipherBlockChainingSubstitutions.java:117) inlining call to CipherBlockChainingSubstitutions.decrypt(Object, byte[], int, int, byte[], int)")) { + System.console(); + } + TTY.println(s); } protected BytecodeParserError asParserError(Throwable e) { @@ -1931,7 +2115,6 @@ public class BytecodeParser implements GraphBuilderContext { return res; } - @SuppressWarnings("try") protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) { try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) { @@ -1943,13 +2126,33 @@ public class BytecodeParser implements GraphBuilderContext { startFrameState.initializeFromArgumentsArray(args); parser.build(this.lastInstr, startFrameState); - FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode(); - this.lastInstr = calleeBeforeReturnNode; - JavaKind calleeReturnKind = targetMethod.getSignature().getReturnKind(); - if (calleeBeforeReturnNode != null) { - ValueNode calleeReturnValue = parser.getReturnValue(); + if (parser.returnDataList == null) { + /* Callee does not return. */ + lastInstr = null; + } else { + ValueNode calleeReturnValue; + MergeNode returnMergeNode = null; + if (s != null) { + s.returnDataList = parser.returnDataList; + } + if (parser.returnDataList.size() == 1) { + /* Callee has a single return, we can continue parsing at that point. */ + ReturnToCallerData singleReturnData = parser.returnDataList.get(0); + lastInstr = singleReturnData.beforeReturnNode; + calleeReturnValue = singleReturnData.returnValue; + } else { + assert parser.returnDataList.size() > 1; + /* Callee has multiple returns, we need to insert a control flow merge. */ + returnMergeNode = graph.add(new MergeNode()); + calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, parser.returnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue); + } + if (calleeReturnValue != null) { - frameState.push(calleeReturnKind.getStackKind(), calleeReturnValue); + frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue); + } + if (returnMergeNode != null) { + returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode)); + lastInstr = finishInstruction(returnMergeNode, frameState); } } @@ -1966,14 +2169,14 @@ public class BytecodeParser implements GraphBuilderContext { return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile); } - protected InvokeNode createInvoke(CallTargetNode callTarget, JavaKind resultType) { - InvokeNode invoke = append(new InvokeNode(callTarget, bci())); + protected InvokeNode createInvoke(int invokeBci, CallTargetNode callTarget, JavaKind resultType) { + InvokeNode invoke = append(new InvokeNode(callTarget, invokeBci)); frameState.pushReturn(resultType, invoke); invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke)); return invoke; } - protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, JavaKind resultType) { + protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType) { if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) { /* * Clear non-live locals early so that the exception handler entry gets the cleared @@ -1983,7 +2186,7 @@ public class BytecodeParser implements GraphBuilderContext { } AbstractBeginNode exceptionEdge = handleException(null, bci()); - InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); + InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci)); frameState.pushReturn(resultType, invoke); invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke)); return invoke; @@ -2012,27 +2215,18 @@ public class BytecodeParser implements GraphBuilderContext { } } } + + frameState.setRethrowException(false); + frameState.clearStack(); + beforeReturn(returnVal, returnKind); if (parent == null) { - frameState.setRethrowException(false); - frameState.clearStack(); - beforeReturn(returnVal, returnKind); append(new ReturnNode(returnVal)); } else { - if (blockMap.getReturnCount() == 1 || !controlFlowSplit) { - // There is only a single return. - beforeReturn(returnVal, returnKind); - this.returnValue = returnVal; - this.beforeReturnNode = this.lastInstr; - this.lastInstr = null; - } else { - frameState.setRethrowException(false); - frameState.clearStack(); - if (returnVal != null) { - frameState.push(returnKind, returnVal); - } - assert blockMap.getReturnCount() > 1; - appendGoto(blockMap.getReturnBlock()); + if (returnDataList == null) { + returnDataList = new ArrayList<>(); } + returnDataList.add(new ReturnToCallerData(returnVal, lastInstr)); + lastInstr = null; } } @@ -2051,7 +2245,11 @@ public class BytecodeParser implements GraphBuilderContext { genInfoPointNode(InfopointReason.METHOD_END, x); if (finalBarrierRequired) { assert originalReceiver != null; - append(new FinalFieldBarrierNode(originalReceiver)); + /* + * When compiling an OSR with a final field store, don't bother tracking the original + * receiver since the receiver cannot be EA'ed. + */ + append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null)); } synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind); } @@ -2076,7 +2274,7 @@ public class BytecodeParser implements GraphBuilderContext { if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject))); } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, escapedReturnValue)); + MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedReturnValue)); monitorExit.setStateAfter(createFrameState(bci, monitorExit)); } @@ -2102,8 +2300,8 @@ public class BytecodeParser implements GraphBuilderContext { JsrScope scope = currentBlock.getJsrScope(); int retAddress = scope.nextReturnAddress(); ConstantNode returnBciNode = getJsrConstant(retAddress); - LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflection); - guard = graph.unique(guard); + LogicNode guard = IntegerEqualsNode.create(constantReflection, metaAccess, options, null, local, returnBciNode); + guard = graph.addOrUniqueWithInputs(guard); append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile)); if (!successor.getJsrScope().equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); @@ -2159,18 +2357,6 @@ public class BytecodeParser implements GraphBuilderContext { @Override public T append(T v) { - if (v.graph() != null) { - return v; - } - T added = graph.addOrUnique(v); - if (added == v) { - updateLastInstruction(v); - } - return added; - } - - @Override - public T recursiveAppend(T v) { if (v.graph() != null) { return v; } @@ -2182,25 +2368,6 @@ public class BytecodeParser implements GraphBuilderContext { } private void updateLastInstruction(T v) { - if (UseGraalInstrumentation.getValue()) { - // resolve instrumentation target - if (v instanceof InstrumentationBeginNode) { - InstrumentationBeginNode begin = (InstrumentationBeginNode) v; - if (!begin.isAnchored() && lastBCI != -1) { - int currentBCI = stream.currentBCI(); - // temporarily set the bytecode stream to lastBCI - stream.setBCI(lastBCI); - // The instrumentation should be associated with the predecessor. In case of the - // predecessor being optimized away, e.g., inlining, we should not set the - // target. - if (stream.nextBCI() == currentBCI) { - begin.setTarget(lastInstr); - } - // restore the current BCI - stream.setBCI(currentBCI); - } - } - } if (v instanceof FixedNode) { FixedNode fixedNode = (FixedNode) v; lastInstr.setNext(fixedNode); @@ -2208,10 +2375,8 @@ public class BytecodeParser implements GraphBuilderContext { FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode; assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end"; lastInstr = fixedWithNextNode; - lastBCI = stream.currentBCI(); } else { lastInstr = null; - lastBCI = -1; } } } @@ -2430,10 +2595,8 @@ public class BytecodeParser implements GraphBuilderContext { setMergeStateAfter(block, firstInstruction); } - if (block == blockMap.getReturnBlock()) { - handleReturnBlock(); - } else if (block == blockMap.getUnwindBlock()) { - handleUnwindBlock(); + if (block == blockMap.getUnwindBlock()) { + handleUnwindBlock((ExceptionDispatchBlock) block); } else if (block instanceof ExceptionDispatchBlock) { createExceptionDispatch((ExceptionDispatchBlock) block); } else { @@ -2443,8 +2606,9 @@ public class BytecodeParser implements GraphBuilderContext { } } - private void handleUnwindBlock() { + private void handleUnwindBlock(ExceptionDispatchBlock block) { if (parent == null) { + finishPrepare(lastInstr, block.deoptBci); frameState.setRethrowException(false); createUnwind(); } else { @@ -2454,15 +2618,6 @@ public class BytecodeParser implements GraphBuilderContext { } } - private void handleReturnBlock() { - JavaKind returnKind = method.getSignature().getReturnKind().getStackKind(); - ValueNode x = returnKind == JavaKind.Void ? null : frameState.pop(returnKind); - assert frameState.stackSize() == 0; - beforeReturn(x, returnKind); - this.returnValue = x; - this.beforeReturnNode = this.lastInstr; - } - private void setMergeStateAfter(BciBlock block, FixedWithNextNode firstInstruction) { AbstractMergeNode abstractMergeNode = (AbstractMergeNode) firstInstruction; if (abstractMergeNode.stateAfter() == null) { @@ -2476,8 +2631,8 @@ public class BytecodeParser implements GraphBuilderContext { private void createUnwind() { assert frameState.stackSize() == 1 : frameState; - ValueNode exception = frameState.pop(JavaKind.Object); synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null); + ValueNode exception = frameState.pop(JavaKind.Object); append(new UnwindNode(exception)); } @@ -2488,6 +2643,7 @@ public class BytecodeParser implements GraphBuilderContext { } genMonitorExit(methodSynchronizedObject, currentReturnValue, bci); assert !frameState.rethrowException(); + finishPrepare(lastInstr, bci); } if (frameState.lockDepth(false) != 0) { throw bailout("unbalanced monitors: too few exits exiting frame"); @@ -2652,7 +2808,7 @@ public class BytecodeParser implements GraphBuilderContext { } private DebugCloseable openNodeContext() { - if (graphBuilderConfig.trackNodeSourcePosition() && !parsingIntrinsic()) { + if ((graphBuilderConfig.trackNodeSourcePosition() || (Debug.isDumpEnabledForMethod() && DumpWithInfopoints.getValue(options))) && !parsingIntrinsic()) { return graph.withNodeSourcePosition(createBytecodePosition()); } return null; @@ -2715,7 +2871,7 @@ public class BytecodeParser implements GraphBuilderContext { } private boolean traceState() { - if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) { + if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE && Debug.isLogEnabled()) { frameState.traceState(); } return true; @@ -2727,12 +2883,6 @@ public class BytecodeParser implements GraphBuilderContext { BciBlock trueBlock = currentBlock.getSuccessor(0); BciBlock falseBlock = currentBlock.getSuccessor(1); - FrameState stateBefore = null; - ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); - } - if (trueBlock == falseBlock) { // The target block is the same independent of the condition. appendGoto(trueBlock); @@ -2753,8 +2903,21 @@ public class BytecodeParser implements GraphBuilderContext { // Check whether the condition needs to negate the result. boolean negate = cond.canonicalNegate(); + genIf(condition, negate, trueBlock, falseBlock); + } + + protected void genIf(LogicNode conditionInput, boolean negateCondition, BciBlock trueBlockInput, BciBlock falseBlockInput) { + BciBlock trueBlock = trueBlockInput; + BciBlock falseBlock = falseBlockInput; + LogicNode condition = conditionInput; + FrameState stateBefore = null; + ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); + if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { + stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); + } // Remove a logic negation node and fold it into the negate boolean. + boolean negate = negateCondition; if (condition instanceof LogicNegationNode) { LogicNegationNode logicNegationNode = (LogicNegationNode) condition; negate = !negate; @@ -2765,7 +2928,7 @@ public class BytecodeParser implements GraphBuilderContext { genConstantTargetIf(trueBlock, falseBlock, negate, condition); } else { if (condition.graph() == null) { - condition = graph.unique(condition); + condition = genUnique(condition); } // Need to get probability based on current bci. @@ -2815,13 +2978,6 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability); postProcessIfNode(ifNode); append(ifNode); - if (parsingIntrinsic()) { - if (x instanceof BranchProbabilityNode) { - ((BranchProbabilityNode) x).simplify(null); - } else if (y instanceof BranchProbabilityNode) { - ((BranchProbabilityNode) y).simplify(null); - } - } } } @@ -3039,6 +3195,19 @@ public class BytecodeParser implements GraphBuilderContext { frameState.push(kind, value); } + public void loadLocalObject(int index) { + ValueNode value = frameState.loadLocal(index, JavaKind.Object); + + int nextBCI = stream.nextBCI(); + int nextBC = stream.readUByte(nextBCI); + if (nextBCI <= currentBlock.endBci && nextBC == Bytecodes.GETFIELD) { + stream.next(); + genGetField(lookupField(stream.readCPI(), Bytecodes.GETFIELD), value); + } else { + frameState.push(JavaKind.Object, value); + } + } + public void storeLocal(JavaKind kind, int index) { ValueNode value = frameState.pop(kind); frameState.storeLocal(index, kind, value); @@ -3320,7 +3489,7 @@ public class BytecodeParser implements GraphBuilderContext { } private JavaTypeProfile getProfileForTypeCheck(TypeReference type) { - if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || type.isExact()) { + if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints(getOptions()) || type.isExact()) { return null; } else { return profilingInfo.getTypeProfile(bci()); @@ -3348,7 +3517,7 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode castNode = null; if (profile != null) { if (profile.getNullSeen().isFalse()) { - object = appendNullCheck(object); + object = nullCheckedValue(object); ResolvedJavaType singleType = profile.asSingleType(); if (singleType != null && checkedType.getType().isAssignableFrom(singleType)) { LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile)); @@ -3356,36 +3525,25 @@ public class BytecodeParser implements GraphBuilderContext { castNode = object; } else { FixedGuardNode fixedGuard = append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(new PiNode(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard)); + castNode = append(PiNode.create(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard)); } } } } + + boolean nonNull = ((ObjectStamp) object.stamp()).nonNull(); if (castNode == null) { LogicNode condition = genUnique(createInstanceOfAllowNull(checkedType, object, null)); if (condition.isTautology()) { castNode = object; } else { FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(new PiNode(object, StampFactory.object(checkedType), fixedGuard)); + castNode = append(PiNode.create(object, StampFactory.object(checkedType, nonNull), fixedGuard)); } } frameState.push(JavaKind.Object, castNode); } - private ValueNode appendNullCheck(ValueNode object) { - if (object.stamp() instanceof AbstractPointerStamp) { - AbstractPointerStamp stamp = (AbstractPointerStamp) object.stamp(); - if (stamp.nonNull()) { - return object; - } - } - - LogicNode isNull = append(IsNullNode.create(object)); - FixedGuardNode fixedGuard = append(new FixedGuardNode(isNull, DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true)); - return append(new PiNode(object, object.stamp().join(StampFactory.objectNonNull()), fixedGuard)); - } - private void genInstanceOf() { int cpi = getStream().readCPI(); JavaType type = lookupType(cpi, INSTANCEOF); @@ -3407,7 +3565,7 @@ public class BytecodeParser implements GraphBuilderContext { LogicNode instanceOfNode = null; if (profile != null) { if (profile.getNullSeen().isFalse()) { - object = appendNullCheck(object); + object = nullCheckedValue(object); ResolvedJavaType singleType = profile.asSingleType(); if (singleType != null) { LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile)); @@ -3421,7 +3579,23 @@ public class BytecodeParser implements GraphBuilderContext { if (instanceOfNode == null) { instanceOfNode = createInstanceOf(resolvedType, object, null); } - frameState.push(JavaKind.Int, append(genConditional(genUnique(instanceOfNode)))); + LogicNode logicNode = genUnique(instanceOfNode); + + int next = getStream().nextBCI(); + int value = getStream().readUByte(next); + if (next <= currentBlock.endBci && (value == Bytecodes.IFEQ || value == Bytecodes.IFNE)) { + getStream().next(); + BciBlock firstSucc = currentBlock.getSuccessor(0); + BciBlock secondSucc = currentBlock.getSuccessor(1); + if (firstSucc != secondSucc) { + genIf(instanceOfNode, value != Bytecodes.IFNE, firstSucc, secondSucc); + } else { + appendGoto(firstSucc); + } + } else { + // Most frequent for value is IRETURN, followed by ISTORE. + frameState.push(JavaKind.Int, append(genConditional(logicNode))); + } } void genNewInstance(int cpi) { @@ -3513,9 +3687,9 @@ public class BytecodeParser implements GraphBuilderContext { ResolvedJavaType resolvedType = (ResolvedJavaType) type; ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin(); - if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType.getArrayClass())) { + if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) { FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); - classInitializationPlugin.apply(this, resolvedType.getArrayClass(), stateBefore); + classInitializationPlugin.apply(this, resolvedType, stateBefore); } ValueNode length = frameState.pop(JavaKind.Int); @@ -3543,9 +3717,9 @@ public class BytecodeParser implements GraphBuilderContext { ResolvedJavaType resolvedType = (ResolvedJavaType) type; ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin(); - if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType.getArrayClass())) { + if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) { FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); - classInitializationPlugin.apply(this, resolvedType.getArrayClass(), stateBefore); + classInitializationPlugin.apply(this, resolvedType, stateBefore); } for (int i = rank - 1; i >= 0; i--) { @@ -3562,15 +3736,21 @@ public class BytecodeParser implements GraphBuilderContext { } private void genGetField(JavaField field) { - ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + genGetField(field, frameState.pop(JavaKind.Object)); + } - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { + private void genGetField(JavaField field, ValueNode receiverInput) { + ValueNode receiver = emitExplicitExceptions(receiverInput); + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + genGetField(resolvedField, receiver); + } else { handleUnresolvedLoadField(field, receiver); - return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; + } - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + private void genGetField(ResolvedJavaField resolvedField, ValueNode receiver) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3580,8 +3760,8 @@ public class BytecodeParser implements GraphBuilderContext { } } - frameState.push(field.getJavaKind(), append(genLoadField(receiver, resolvedField))); - if (resolvedField.getName().equals("referent") && resolvedField.getDeclaringClass().equals(metaAccess.lookupJavaType(Reference.class))) { + frameState.push(resolvedField.getJavaKind(), append(genLoadField(receiver, resolvedField))); + if (resolvedField.getDeclaringClass().getName().equals("Ljava/lang/ref/Reference;") && resolvedField.getName().equals("referent")) { LocationIdentity referentIdentity = new FieldLocationIdentity(resolvedField); append(new MembarNode(0, referentIdentity)); } @@ -3591,61 +3771,71 @@ public class BytecodeParser implements GraphBuilderContext { * @param receiver the receiver of an object based operation * @param index the index of an array based operation that is to be tested for out of bounds. * This is null for a non-array operation. - * @return the receiver value possibly modified to have a tighter stamp + * @return the receiver value possibly modified to have a non-null stamp */ protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) { - assert receiver != null; - if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) { - return receiver; - } - if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile && (profilingInfo == null || - (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue()))) { - return receiver; - } - - ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); - if (index != null) { + if (needsExplicitException()) { + ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); ValueNode length = append(genArrayLength(nonNullReceiver)); emitExplicitBoundsCheck(index, length); + return nonNullReceiver; } - EXPLICIT_EXCEPTIONS.increment(); - return nonNullReceiver; + return receiver; + } + + protected ValueNode emitExplicitExceptions(ValueNode receiver) { + if (StampTool.isPointerNonNull(receiver) || !needsExplicitException()) { + return receiver; + } else { + return emitExplicitNullCheck(receiver); + } + } + + private boolean needsExplicitException() { + BytecodeExceptionMode exceptionMode = graphBuilderConfig.getBytecodeExceptionMode(); + if (exceptionMode == BytecodeExceptionMode.CheckAll || StressExplicitExceptionCode.getValue(options)) { + return true; + } else if (exceptionMode == BytecodeExceptionMode.Profile && profilingInfo != null) { + return profilingInfo.getExceptionSeen(bci()) == TriState.TRUE; + } + return false; } private void genPutField(JavaField field) { - ValueNode value = frameState.pop(field.getJavaKind()); - ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + genPutField(field, frameState.pop(field.getJavaKind())); + } - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - handleUnresolvedStoreField(field, value, receiver); - return; - } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; + private void genPutField(JavaField field, ValueNode value) { + ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object)); + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { - graph.recordField(resolvedField); - } - - for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { - if (plugin.handleStoreField(this, receiver, resolvedField, value)) { - return; + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { + graph.recordField(resolvedField); } - } - if (resolvedField.isFinal() && method.isConstructor()) { - finalBarrierRequired = true; + for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { + if (plugin.handleStoreField(this, receiver, resolvedField, value)) { + return; + } + } + + if (resolvedField.isFinal() && method.isConstructor()) { + finalBarrierRequired = true; + } + genStoreField(receiver, resolvedField, value); + } else { + handleUnresolvedStoreField(field, value, receiver); } - genStoreField(receiver, resolvedField, value); } private void genGetStatic(JavaField field) { - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - handleUnresolvedLoadField(field, null); + ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, null); + if (resolvedField == null) { return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3673,15 +3863,41 @@ public class BytecodeParser implements GraphBuilderContext { frameState.push(field.getJavaKind(), append(genLoadField(null, resolvedField))); } + private ResolvedJavaField resolveStaticFieldAccess(JavaField field, ValueNode value) { + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + if (resolvedField.getDeclaringClass().isInitialized()) { + return resolvedField; + } + /* + * Static fields have initialization semantics but may be safely accessed under certain + * conditions while the class is being initialized. Executing in the clinit or init of + * classes which are subtypes of the field holder are sure to be running in a context + * where the access is safe. + */ + if (resolvedField.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) { + if (method.isClassInitializer() || method.isConstructor()) { + return resolvedField; + } + } + } + if (value == null) { + handleUnresolvedLoadField(field, null); + } else { + handleUnresolvedStoreField(field, value, null); + + } + return null; + } + private void genPutStatic(JavaField field) { ValueNode value = frameState.pop(field.getJavaKind()); - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - handleUnresolvedStoreField(field, value, null); + ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, value); + if (resolvedField == null) { return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3741,12 +3957,10 @@ public class BytecodeParser implements GraphBuilderContext { int nofCases = bs.numberOfCases(); double[] keyProbabilities = switchProbability(nofCases + 1, bci); - Map bciToBlockSuccessorIndex = new HashMap<>(); + EconomicMap bciToBlockSuccessorIndex = EconomicMap.create(Equivalence.DEFAULT); for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci); - if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) { - bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); - } + bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); } ArrayList actualSuccessors = new ArrayList<>(); @@ -3782,7 +3996,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected boolean isNeverExecutedCode(double probability) { - return probability == 0 && optimisticOpts.removeNeverExecutedCode(); + return probability == 0 && optimisticOpts.removeNeverExecutedCode(getOptions()); } protected double branchProbability() { @@ -3797,7 +4011,7 @@ public class BytecodeParser implements GraphBuilderContext { probability = 0.5; } - if (!optimisticOpts.removeNeverExecutedCode()) { + if (!optimisticOpts.removeNeverExecutedCode(getOptions())) { if (probability == 0) { probability = 0.0000001; } else if (probability == 1) { @@ -3863,7 +4077,7 @@ public class BytecodeParser implements GraphBuilderContext { case LLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Long); break; case FLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Float); break; case DLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Double); break; - case ALOAD : loadLocal(stream.readLocalIndex(), JavaKind.Object); break; + case ALOAD : loadLocalObject(stream.readLocalIndex()); break; case ILOAD_0 : // fall through case ILOAD_1 : // fall through case ILOAD_2 : // fall through @@ -3883,7 +4097,7 @@ public class BytecodeParser implements GraphBuilderContext { case ALOAD_0 : // fall through case ALOAD_1 : // fall through case ALOAD_2 : // fall through - case ALOAD_3 : loadLocal(opcode - ALOAD_0, JavaKind.Object); break; + case ALOAD_3 : loadLocalObject(opcode - ALOAD_0); break; case IALOAD : genLoadIndexed(JavaKind.Int ); break; case LALOAD : genLoadIndexed(JavaKind.Long ); break; case FALOAD : genLoadIndexed(JavaKind.Float ); break; @@ -4047,7 +4261,7 @@ public class BytecodeParser implements GraphBuilderContext { } private void genArrayLength() { - ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object)); frameState.push(JavaKind.Int, append(genArrayLength(array))); } @@ -4066,7 +4280,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { - if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { + if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { traceInstructionHelper(bci, opcode, blockStart); } return true; @@ -4107,11 +4321,4 @@ public class BytecodeParser implements GraphBuilderContext { static String nSpaces(int n) { return n == 0 ? "" : format("%" + n + "s", ""); } - - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java index 9328c7614b0..18dd5efee1a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java @@ -24,8 +24,7 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Options related to {@link BytecodeParser}. @@ -36,30 +35,37 @@ import org.graalvm.compiler.options.StableOptionValue; public class BytecodeParserOptions { // @formatter:off @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) - public static final OptionValue TraceBytecodeParserLevel = new OptionValue<>(0); + public static final OptionKey TraceBytecodeParserLevel = new OptionKey<>(0); @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(true); + public static final OptionKey InlineDuringParsing = new OptionKey<>(true); + + @Option(help = "Inlines partial intrinsic exits during bytecode parsing when possible. " + + "A partial intrinsic exit is a call within an intrinsic to the method " + + "being intrinsified and denotes semantics of the original method that " + + "the intrinsic does not support.", type = OptionType.Expert) + public static final OptionKey InlinePartialIntrinsicExitDuringParsing = new OptionKey<>(true); @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineIntrinsicsDuringParsing = new StableOptionValue<>(true); + public static final OptionKey InlineIntrinsicsDuringParsing = new OptionKey<>(true); @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); + public static final OptionKey TraceInlineDuringParsing = new OptionKey<>(false); @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceParserPlugins = new StableOptionValue<>(false); + public static final OptionKey TraceParserPlugins = new OptionKey<>(false); @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); - - @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false); + public static final OptionKey InlineDuringParsingMaxDepth = new OptionKey<>(10); @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug) - public static final OptionValue HideSubstitutionStates = new OptionValue<>(false); + public static final OptionKey HideSubstitutionStates = new OptionKey<>(false); @Option(help = "Use intrinsics guarded by a virtual dispatch test at indirect call sites.", type = OptionType.Debug) - public static final OptionValue UseGuardedIntrinsics = new OptionValue<>(true); + public static final OptionKey UseGuardedIntrinsics = new OptionKey<>(true); + + // Remove once GR-3604 reduces the memory overhead of including node source info dumps + @Option(help = "Enable node source positions if dumping is enabled.", type = OptionType.Debug) + public static final OptionKey DumpWithInfopoints = new OptionKey<>(false); // @formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java index c2cc0ae369f..94bcf84ea10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java @@ -23,8 +23,6 @@ package org.graalvm.compiler.java; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; @@ -36,6 +34,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; +import org.graalvm.util.EconomicMap; public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure { @@ -54,7 +53,11 @@ public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.N @Override protected Double merge(AbstractMergeNode merge, List states) { // a merge has the sum of all predecessor probabilities - return states.stream().collect(Collectors.summingDouble(d -> d)); + double result = 0.0; + for (double d : states) { + result += d; + } + return result; } @Override @@ -65,10 +68,13 @@ public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.N } @Override - protected Map processLoop(LoopBeginNode loop, Double initialState) { - Map exitStates = ReentrantNodeIterator.processLoop(this, loop, 1D).exitStates; + protected EconomicMap processLoop(LoopBeginNode loop, Double initialState) { + EconomicMap exitStates = ReentrantNodeIterator.processLoop(this, loop, 1D).exitStates; - double exitProbability = exitStates.values().stream().mapToDouble(d -> d).sum(); + double exitProbability = 0.0; + for (double d : exitStates.getValues()) { + exitProbability += d; + } exitProbability = Math.min(1D, exitProbability); if (exitProbability < ControlFlowGraph.MIN_PROBABILITY) { exitProbability = ControlFlowGraph.MIN_PROBABILITY; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java similarity index 81% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java index 8be604a4a87..b123ed6ea85 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java @@ -25,24 +25,25 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +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.Suites; -public class DefaultSuitesProvider extends SuitesProviderBase { +public class DefaultSuitesCreator extends SuitesProviderBase { private final CompilerConfiguration compilerConfiguration; - public DefaultSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public DefaultSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(); this.defaultGraphBuilderSuite = createGraphBuilderSuite(plugins); this.compilerConfiguration = compilerConfiguration; } @Override - public Suites createSuites() { - return Suites.createSuites(compilerConfiguration); + public Suites createSuites(OptionValues options) { + return Suites.createSuites(compilerConfiguration, options); } protected PhaseSuite createGraphBuilderSuite(Plugins plugins) { @@ -52,7 +53,7 @@ public class DefaultSuitesProvider extends SuitesProviderBase { } @Override - public LIRSuites createLIRSuites() { - return Suites.createLIRSuites(compilerConfiguration); + public LIRSuites createLIRSuites(OptionValues options) { + return Suites.createLIRSuites(compilerConfiguration, options); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java index 092d213d903..60648c2ee01 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java @@ -42,7 +42,8 @@ import java.util.function.Function; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.Debug; @@ -99,6 +100,7 @@ public final class FrameStateBuilder implements SideEffectsState { private MonitorIdNode[] monitorIds; private final StructuredGraph graph; + private final boolean clearNonLiveLocals; private FrameState outerFrameState; /** @@ -142,6 +144,7 @@ public final class FrameStateBuilder implements SideEffectsState { this.monitorIds = EMPTY_MONITOR_ARRAY; this.graph = graph; + this.clearNonLiveLocals = GraalOptions.OptClearNonLiveLocals.getValue(graph.getOptions()); this.canVerifyKind = true; } @@ -263,6 +266,7 @@ public final class FrameStateBuilder implements SideEffectsState { assert other.graph != null; graph = other.graph; + clearNonLiveLocals = other.clearNonLiveLocals; monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); assert locals.length == code.getMaxLocals(); @@ -303,7 +307,8 @@ public final class FrameStateBuilder implements SideEffectsState { public FrameState create(int bci, StateSplit forStateSplit) { if (parser != null && parser.parsingIntrinsic()) { - return parser.intrinsicContext.createFrameState(parser.getGraph(), this, forStateSplit); + NodeSourcePosition sourcePosition = createBytecodePosition(bci, false); + return parser.intrinsicContext.createFrameState(parser.getGraph(), this, forStateSplit, sourcePosition); } // Skip intrinsic frames @@ -346,8 +351,12 @@ public final class FrameStateBuilder implements SideEffectsState { } public NodeSourcePosition createBytecodePosition(int bci) { + return createBytecodePosition(bci, HideSubstitutionStates.getValue(parser.graph.getOptions())); + } + + private NodeSourcePosition createBytecodePosition(int bci, boolean hideSubstitutionStates) { BytecodeParser parent = parser.getParent(); - if (HideSubstitutionStates.getValue()) { + if (hideSubstitutionStates) { if (parser.parsingIntrinsic()) { // Attribute to the method being replaced return new NodeSourcePosition(constantReceiver, parent.getFrameStateBuilder().createBytecodePosition(parent.bci()), parser.intrinsicContext.getOriginalMethod(), -1); @@ -355,13 +364,13 @@ public final class FrameStateBuilder implements SideEffectsState { // Skip intrinsic frames parent = parser.getNonIntrinsicAncestor(); } - return create(null, constantReceiver, bci, parent); + return create(null, constantReceiver, bci, parent, hideSubstitutionStates); } - private NodeSourcePosition create(NodeSourcePosition o, JavaConstant receiver, int bci, BytecodeParser parent) { + private NodeSourcePosition create(NodeSourcePosition o, JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) { NodeSourcePosition outer = o; if (outer == null && parent != null) { - outer = parent.getFrameStateBuilder().createBytecodePosition(parent.bci()); + outer = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates); } if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) { return FrameState.toSourcePosition(outerFrameState); @@ -624,7 +633,7 @@ public final class FrameStateBuilder implements SideEffectsState { * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with * Kind.Illegal, because the conflicting branch might not have been parsed. */ - if (!parser.graphBuilderConfig.clearNonLiveLocals()) { + if (!clearNonLiveLocals) { return; } if (liveIn) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java index 8baadb649e9..47e4b9333ab 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.java; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; public class JsrNotSupportedBailout extends PermanentBailoutException { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java index 025fe1f16c4..2244df3c80b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java @@ -23,8 +23,7 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.lir.phases.LIRSuites; -import org.graalvm.compiler.options.DerivedOptionValue; -import org.graalvm.compiler.options.DerivedOptionValue.OptionSupplier; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; @@ -32,44 +31,11 @@ import org.graalvm.compiler.phases.tiers.SuitesCreator; public abstract class SuitesProviderBase implements SuitesCreator { - protected final DerivedOptionValue defaultSuites; protected PhaseSuite defaultGraphBuilderSuite; - protected final DerivedOptionValue defaultLIRSuites; - - private class SuitesSupplier implements OptionSupplier { - - private static final long serialVersionUID = 2677805381215454728L; - - @Override - public Suites get() { - Suites suites = createSuites(); - suites.setImmutable(); - return suites; - } - - } - - private class LIRSuitesSupplier implements OptionSupplier { - - private static final long serialVersionUID = 312070237227476252L; - - @Override - public LIRSuites get() { - LIRSuites lirSuites = createLIRSuites(); - lirSuites.setImmutable(); - return lirSuites; - } - - } - - public SuitesProviderBase() { - this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); - this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); - } @Override - public final Suites getDefaultSuites() { - return defaultSuites.getValue(); + public final Suites getDefaultSuites(OptionValues options) { + return createSuites(options); } @Override @@ -78,13 +44,13 @@ public abstract class SuitesProviderBase implements SuitesCreator { } @Override - public final LIRSuites getDefaultLIRSuites() { - return defaultLIRSuites.getValue(); + public final LIRSuites getDefaultLIRSuites(OptionValues options) { + return createLIRSuites(options); } @Override - public abstract LIRSuites createLIRSuites(); + public abstract LIRSuites createLIRSuites(OptionValues options); @Override - public abstract Suites createSuites(); + public abstract Suites createSuites(OptionValues options); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java index d240feec5ca..36807d30474 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java @@ -23,24 +23,23 @@ package org.graalvm.compiler.jtt; import static java.lang.reflect.Modifier.isStatic; - import java.util.Collections; import java.util.Set; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assert; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Base class for the JTT tests. @@ -65,8 +64,8 @@ public class JTTTest extends GraalCompilerTest { } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId); + protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId, options); if (argsToBind != null) { Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); @@ -82,8 +81,8 @@ public class JTTTest extends GraalCompilerTest { } @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - return super.getCode(method, graph, argsToBind != null); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + return super.getCode(method, graph, argsToBind != null, installAsDefault, options); } Double delta; @@ -104,14 +103,18 @@ public class JTTTest extends GraalCompilerTest { } protected void runTest(String name, Object... args) { - runTest(EMPTY, name, args); + runTest(getInitialOptions(), name, args); + } + + protected void runTest(OptionValues options, String name, Object... args) { + runTest(options, EMPTY, true, false, name, args); } protected void runTest(Set shouldNotDeopt, String name, Object... args) { - runTest(shouldNotDeopt, true, false, name, args); + runTest(getInitialOptions(), shouldNotDeopt, true, false, name, args); } - protected void runTest(Set shouldNotDeopt, boolean bind, boolean noProfile, String name, Object... args) { + protected void runTest(OptionValues options, Set shouldNotDeopt, boolean bind, boolean noProfile, String name, Object... args) { ResolvedJavaMethod method = getResolvedJavaMethod(name); Object receiver = method.isStatic() ? null : this; @@ -121,14 +124,14 @@ public class JTTTest extends GraalCompilerTest { method.reprofile(); } - testAgainstExpected(method, expect, shouldNotDeopt, receiver, args); + testAgainstExpected(options, method, expect, shouldNotDeopt, receiver, args); if (args.length > 0 && bind) { if (noProfile) { method.reprofile(); } this.argsToBind = args; - testAgainstExpected(method, expect, shouldNotDeopt, receiver, args); + testAgainstExpected(options, method, expect, shouldNotDeopt, receiver, args); this.argsToBind = null; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java index f358e1008e3..d6fdc91ada2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java @@ -24,15 +24,13 @@ package org.graalvm.compiler.jtt.backend; import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; - +import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize; import java.lang.reflect.Method; import org.junit.Test; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; public class ConstantPhiTest extends JTTTest { @@ -59,24 +57,18 @@ public class ConstantPhiTest extends JTTTest { @Test @SuppressWarnings("try") public void run0() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", 0, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", 0, 0xDEADDEAD); } @Test @SuppressWarnings("try") public void run1() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", -1, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", -1, 0xDEADDEAD); } @Test @SuppressWarnings("try") public void run2() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", 1, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", 1, 0xDEADDEAD); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java index a48e6cd4763..a856a9d518c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,54 +22,82 @@ */ package org.graalvm.compiler.jtt.backend; -import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; -import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; -import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; -import static jdk.internal.org.objectweb.asm.Opcodes.IFNE; -import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC; -import static jdk.internal.org.objectweb.asm.Opcodes.LADD; -import static jdk.internal.org.objectweb.asm.Opcodes.LCMP; -import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0; -import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD; -import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN; -import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; +import static org.objectweb.asm.Opcodes.ACC_FINAL; +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACC_STATIC; +import static org.objectweb.asm.Opcodes.ACC_SUPER; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.LRETURN; -import org.junit.BeforeClass; -import org.junit.Test; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; import org.graalvm.compiler.test.ExportingClassLoader; +import org.junit.Before; +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; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import junit.framework.AssertionFailedError; +/** + * This test let the compiler deal with a large amount of constant data in a method. This data is + * stored typically in the constant section of the native method. Especially on the SPARC platform + * the backend can address only 8k of memory with an immediate offset. Beyond this barrier, a + * different addressing mode must be used. + * + * In order to do this this test generates a large method containing a large switch statement in + * form of + * + * + * static long run(long a) { + * switch(a) { + * case 1: + * return 0xF0F0F0F0F0L + 1; + * case 2: + * return 0xF0F0F0F0F0L + 2; + * .... + * default: + * return 0; + * } + * + * } + * + * + */ +@RunWith(Parameterized.class) public class LargeConstantSectionTest extends JTTTest { private static final String NAME = "LargeConstantSection"; private static final long LARGE_CONSTANT = 0xF0F0F0F0F0L; private static LargeConstantClassLoader LOADER; + @Parameter(value = 0) public int numberBlocks; - @BeforeClass - public static void before() { + @Parameters(name = "{0}") + public static Collection data() { + List parameters = new ArrayList<>(); + for (int i = 4; i < 13; i += 2) { + parameters.add(new Object[]{1 << i}); + } + return parameters; + } + + @Before + public void before() { LOADER = new LargeConstantClassLoader(LargeConstantSectionTest.class.getClassLoader()); } - public abstract static class LargeConstantAbstract { - public abstract long run(long i); - } - - public static long test(LargeConstantAbstract a, long i) throws Exception { - return a.run(GraalDirectives.opaque(i)); - } - - public static class LargeConstantClassLoader extends ExportingClassLoader { + public class LargeConstantClassLoader extends ExportingClassLoader { public LargeConstantClassLoader(ClassLoader parent) { super(parent); } @@ -77,54 +105,38 @@ public class LargeConstantSectionTest extends JTTTest { @Override protected Class findClass(String name) throws ClassNotFoundException { if (name.equals(NAME)) { - String graalDirectivesClassName = GraalDirectives.class.getName().replace('.', '/'); - int numberIfBlocks = 1100; // Each if block contains three constants ClassWriter cw = new ClassWriter(0); MethodVisitor mv; - String abstractClassName = Type.getInternalName(LargeConstantAbstract.class); - cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, abstractClassName, null); + cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, "java/lang/Object", null); - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "run", "(I)J", null, null); mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, abstractClassName, "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC, "run", "(J)J", null, null); - mv.visitCode(); - Label nextIf = new Label(); - for (int i = 0; i < numberIfBlocks; i++) { - mv.visitLabel(nextIf); - mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{}); - mv.visitVarInsn(LLOAD, 1); + Label begin = new Label(); + mv.visitLabel(begin); + mv.visitVarInsn(ILOAD, 0); + Label[] labels = new Label[numberBlocks]; + int[] keys = new int[numberBlocks]; + for (int i = 0; i < labels.length; i++) { + labels[i] = new Label(); + keys[i] = i; + } + Label defaultLabel = new Label(); + mv.visitLookupSwitchInsn(defaultLabel, keys, labels); + for (int i = 0; i < labels.length; i++) { + mv.visitLabel(labels[i]); + mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{}); mv.visitLdcInsn(new Long(LARGE_CONSTANT + i)); - mv.visitInsn(LCMP); - nextIf = new Label(); - mv.visitJumpInsn(IFNE, nextIf); - mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks)); - mv.visitMethodInsn(INVOKESTATIC, graalDirectivesClassName, "opaque", "(J)J", false); - mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks * 2)); - mv.visitMethodInsn(INVOKESTATIC, graalDirectivesClassName, "opaque", "(J)J", false); - mv.visitInsn(LADD); mv.visitInsn(LRETURN); } - mv.visitLabel(nextIf); - mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{}); - mv.visitInsn(LCONST_0); + mv.visitLabel(defaultLabel); + mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{}); + mv.visitLdcInsn(new Long(3L)); mv.visitInsn(LRETURN); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(4, 6); + Label end = new Label(); + mv.visitLabel(end); + mv.visitLocalVariable("a", "I", null, begin, end, 0); + mv.visitMaxs(2, 1); mv.visitEnd(); - - cw.visitEnd(); - byte[] bytes = cw.toByteArray(); return defineClass(name, bytes, 0, bytes.length); } else { @@ -136,8 +148,20 @@ public class LargeConstantSectionTest extends JTTTest { @Test @SuppressWarnings("try") public void run0() throws Exception { - try (OverrideScope os = OptionValue.override(GraalOptions.InlineEverything, true)) { - runTest("test", LOADER.findClass(NAME).newInstance(), 0L); + test("run", numberBlocks - 3); + } + + @Override + protected ResolvedJavaMethod getResolvedJavaMethod(String methodName) { + try { + for (Method method : LOADER.findClass(NAME).getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + return asResolvedJavaMethod(method); + } + } + } catch (ClassNotFoundException e) { + throw new AssertionFailedError("Cannot find class " + NAME); } + throw GraalError.shouldNotReachHere(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java index 4545fdbc1b1..a2570035d21 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java @@ -76,4 +76,20 @@ public class BC_instanceof extends JTTTest { runTest("test", 4); } + // Checkstyle: stop + // Need to stop checkstyle due to empty if constructs. + public static boolean testEmpty(Object obj) { + if (obj instanceof TestClass) { + } + + if (!(obj instanceof TestClass)) { + } + return true; + } + // Checkstyle: resume + + @Test + public void run5() throws Throwable { + runTest("testEmpty", object2); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java index 791ee24aed6..599dce74853 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java @@ -26,8 +26,7 @@ import org.junit.Test; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; /** @@ -89,10 +88,8 @@ public class BC_instanceof01 extends JTTTest { @Override @SuppressWarnings("try") - protected Suites getSuites() { - try (OverrideScope scope = OptionValue.override(HighTier.Options.Inline, false)) { - return super.getSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(new OptionValues(options, HighTier.Options.Inline, false)); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_newarray_02.java similarity index 62% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRKindTool.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_newarray_02.java index c7f58516521..41c6d25518d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_newarray_02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,23 +20,33 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.hotspot.sparc; +package org.graalvm.compiler.jtt.bytecode; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.sparc.SPARCLIRKindTool; -import org.graalvm.compiler.hotspot.nodes.type.HotSpotLIRKindTool; +import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; -import jdk.vm.ci.sparc.SPARCKind; - -public class SPARCHotSpotLIRKindTool extends SPARCLIRKindTool implements HotSpotLIRKindTool { - - @Override - public LIRKind getNarrowOopKind() { - return LIRKind.reference(SPARCKind.WORD); +public class BC_newarray_02 extends JTTTest { + public static byte[] test(int l) { + return new byte[l]; } - @Override - public LIRKind getNarrowPointerKind() { - return LIRKind.value(SPARCKind.WORD); + @Test + public void testZero() { + runTest("test", 0); + } + + @Test + public void testOne() { + runTest("test", 1); + } + + @Test + public void testNegative() { + runTest("test", -1); + } + + @Test + public void testLarge() { + runTest("test", 17 * 1024 * 1024); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java index 1753afa108a..783aa17506e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java @@ -47,7 +47,7 @@ public class BC_getfield1 extends JTTTest { @Test public void run1() throws Throwable { // tests that the null check isn't removed along with the read - runTest(EMPTY, true, true, "test", (Object) null); + runTest(getInitialOptions(), EMPTY, true, true, "test", (Object) null); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java index ac939571007..b140a67742e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java @@ -22,16 +22,14 @@ */ package org.graalvm.compiler.jtt.except; -import org.junit.BeforeClass; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.test.ExportingClassLoader; - -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; public class UntrustedInterfaces extends JTTTest { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java index df296683e2c..6a64c0ea57f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java @@ -24,15 +24,18 @@ package org.graalvm.compiler.jtt.hotspot; import java.util.ArrayList; -import org.junit.Before; import org.junit.Test; -import org.graalvm.compiler.core.common.util.ArraySet; import org.graalvm.compiler.jtt.JTTTest; // @formatter:off public class Test6186134 extends JTTTest { + @SuppressWarnings("serial") + public static final class MyArrayList extends ArrayList { + + } + public static class TestClass { int num = 0; @@ -45,8 +48,8 @@ public class Test6186134 extends JTTTest { return num-- > 0; } - public ArrayList test1() { - ArrayList res = new ArrayList<>(); + public MyArrayList test1() { + MyArrayList res = new MyArrayList<>(); int maxResults = Integer.MAX_VALUE; int n = 0; boolean more = more(); @@ -70,12 +73,6 @@ public class Test6186134 extends JTTTest { return 0; } - @Before - public void setUp() { - /* Ensure that ArrayList is _not_ a leaf class (otherwise code installation may fail due to a failed leaf type dependency). */ - UNSAFE.ensureClassInitialized(ArraySet.class); - } - @Test public void run0() throws Throwable { runTest("test", 100); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java index 2467c7753d7..e6d027c2b30 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java @@ -22,12 +22,17 @@ */ package org.graalvm.compiler.jtt.hotspot; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Test6959129 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + public static long test() { int min = Integer.MAX_VALUE - 30000; int max = Integer.MAX_VALUE; @@ -74,8 +79,9 @@ public class Test6959129 extends JTTTest { return maxmoves; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java index 815110febe0..73906cd73b2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java @@ -24,30 +24,25 @@ package org.graalvm.compiler.jtt.jdk; import java.lang.reflect.Field; -import org.junit.Test; - -import sun.misc.Unsafe; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; /* */ public class UnsafeAccess01 extends JTTTest { private static int randomValue = 100; - private static final Unsafe unsafe; private static final long offset; private static Object staticObject = new TestClass(); static { - unsafe = getUnsafe(); Field field = null; try { field = TestClass.class.getDeclaredField("field"); } catch (NoSuchFieldException e) { } catch (SecurityException e) { } - offset = unsafe.objectFieldOffset(field); + offset = UNSAFE.objectFieldOffset(field); } private static class TestClass { @@ -56,20 +51,10 @@ public class UnsafeAccess01 extends JTTTest { public static int test() { final TestClass object = new TestClass(); - final int value = unsafe.getInt(object, offset); + final int value = UNSAFE.getInt(object, offset); return value; } - static Unsafe getUnsafe() { - try { - final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - return (Unsafe) unsafeField.get(null); - } catch (Exception e) { - throw new Error(e); - } - } - @Test public void run0() throws Throwable { runTest("test"); @@ -86,11 +71,11 @@ public class UnsafeAccess01 extends JTTTest { final int oldValue = ((TestClass) object).field; if (randomValue == 100) { - unsafe.putInt(object, offset, 41); + UNSAFE.putInt(object, offset, 41); } else { - unsafe.putInt(object, offset, 40); + UNSAFE.putInt(object, offset, 40); } - unsafe.putInt(object, offset, 42); + UNSAFE.putInt(object, offset, 42); return oldValue; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java index 98f0f27cef7..2f1df0cc53e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java @@ -22,21 +22,17 @@ */ package org.graalvm.compiler.jtt.jdk; -import jdk.vm.ci.meta.ResolvedJavaMethod; - +import org.graalvm.compiler.jtt.JTTTest; import org.junit.Test; -import sun.misc.Unsafe; - -import org.graalvm.compiler.jtt.JTTTest; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class Unsafe_compareAndSwap extends JTTTest { - static final Unsafe unsafe = UnsafeAccess01.getUnsafe(); static final long valueOffset; static { try { - valueOffset = unsafe.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); + valueOffset = UNSAFE.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } @@ -44,9 +40,9 @@ public class Unsafe_compareAndSwap extends JTTTest { public static String test(Unsafe_compareAndSwap u, Object o, String expected, String newValue) { // First arg is not an array - can use a field write barrier - unsafe.compareAndSwapObject(u, valueOffset, expected, newValue); + UNSAFE.compareAndSwapObject(u, valueOffset, expected, newValue); // Not known if first arg is an array - different write barrier may be used - unsafe.compareAndSwapObject(o, valueOffset, expected, newValue); + UNSAFE.compareAndSwapObject(o, valueOffset, expected, newValue); return instance.value; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java index 5d109a8dda3..a69bf2d8059 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java @@ -22,19 +22,16 @@ */ package org.graalvm.compiler.jtt.jdk; -import org.junit.Test; - -import sun.misc.Unsafe; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Assume; +import org.junit.Test; public class Unsafe_compareAndSwapNullCheck extends JTTTest { - static final Unsafe unsafe = UnsafeAccess01.getUnsafe(); static final long valueOffset; static { try { - valueOffset = unsafe.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); + valueOffset = UNSAFE.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } @@ -46,11 +43,13 @@ public class Unsafe_compareAndSwapNullCheck extends JTTTest { public static void test(Unsafe_compareAndSwapNullCheck u, long expected, long newValue) { @SuppressWarnings("unused") long l = u.lng; - unsafe.compareAndSwapLong(u, valueOffset, expected, newValue); + UNSAFE.compareAndSwapLong(u, valueOffset, expected, newValue); } @Test public void run0() throws Throwable { - runTest(EMPTY, false, true, "test", null, 1L, 2L); + // GR-2921: Unsafe_compareAndSwapNullCheck test crashes on jdk9 + Assume.assumeTrue(Java8OrEarlier); + runTest(getInitialOptions(), EMPTY, false, true, "test", null, 1L, 2L); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java index cefbae2f970..b7ae49954f6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java @@ -22,21 +22,20 @@ */ package org.graalvm.compiler.jtt.lang; +import static org.graalvm.compiler.core.common.GraalOptions.InlineEverything; + import java.util.EnumSet; import java.util.function.IntBinaryOperator; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Test; + import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.junit.Test; - -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - public class LambdaEagerTest extends GraalCompilerTest { private static final EnumSet UNRESOLVED_UNREACHED = EnumSet.of(DeoptimizationReason.Unresolved, DeoptimizationReason.UnreachedCode); @@ -81,9 +80,8 @@ public class LambdaEagerTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) { - try (OverrideScope scope = OptionValue.override(GraalOptions.InlineEverything, true)) { - return super.getCode(installedCodeOwner, graph, forceCompile); - } + protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + assert graph == null; + return super.getCode(installedCodeOwner, graph, forceCompile, installAsDefault, new OptionValues(options, InlineEverything, true)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java new file mode 100644 index 00000000000..68dacfc81d3 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.optimize; + +import org.junit.Assert; +import org.junit.Test; + +import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.options.OptionValues; + +public class GuardMovement extends JTTTest { + + private static int staticValue; + + private static class A { + int x; + int y; + } + + public int foo(A a) { + Assert.assertNotEquals("a cannot be null, because a field of a is accessed before the call", a, null); + return 42; + } + + @SuppressWarnings("all") + public int test(A a) { + + int value; + int result = 0; + + // Use a condition that folds after floating guards and before guard lowering. + // After disabling PEA and read elimination, the following condition does the trick. + if (staticValue == staticValue) { + // Access a.x to generate a null checked value. + value = a.x; + result = foo(a); + } + + // Access a.y to generate another null checked value. + return result + a.y; + } + + @Test + public void run0() throws Throwable { + OptionValues options = new OptionValues(getInitialOptions(), MaximumInliningSize, -1, GraalOptions.TrivialInliningSize, -1, GraalOptions.PartialEscapeAnalysis, false, + GraalOptions.OptReadElimination, false); + runTest(options, "test", new A()); + runTest(options, "test", new Object[]{null}); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java index b479d7ec5c6..2fa90ad28af 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -38,13 +39,13 @@ import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; public class NestedLoop_EA extends JTTTest { @Override - protected Suites createSuites() { - Suites suites = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites suites = super.createSuites(options); ListIterator> position = suites.getHighTier().findPhase(PartialEscapePhase.class); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); // incremental canonicalizer of PEA is missing some important canonicalization (TODO?) position.add(canonicalizer); - position.add(new PartialEscapePhase(true, canonicalizer)); + position.add(new PartialEscapePhase(true, canonicalizer, options)); return suites; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java index 929bb24b4c7..6275a2009d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java @@ -22,44 +22,30 @@ */ package org.graalvm.compiler.jtt.optimize; -import java.lang.reflect.Field; import java.nio.ByteBuffer; -import org.junit.Test; -import org.junit.internal.AssumptionViolatedException; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import jdk.vm.ci.meta.ResolvedJavaMethod; -import sun.misc.Unsafe; public class UnsafeDeopt extends JTTTest { - private static final Unsafe unsafe; - - static { - try { - final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - unsafe = (Unsafe) unsafeField.get(null); - } catch (Exception e) { - throw new Error(e); - } - } public static int readWriteReadUnsafe(long addr, int m) { - int original = unsafe.getInt(addr); + int original = UNSAFE.getInt(addr); if (original != 0) { return -m; } - unsafe.putInt(addr, m); + UNSAFE.putInt(addr, m); if (m > 10) { if (m > 20) { GraalDirectives.deoptimize(); } - unsafe.putInt(addr + 4, m); + UNSAFE.putInt(addr + 4, m); } - return unsafe.getInt(addr); + return UNSAFE.getInt(addr); } public static int readWriteReadByteBuffer(ByteBuffer buffer, int m) { @@ -78,13 +64,13 @@ public class UnsafeDeopt extends JTTTest { } public long createBuffer() { - long addr = unsafe.allocateMemory(32); - unsafe.setMemory(addr, 32, (byte) 0); + long addr = UNSAFE.allocateMemory(32); + UNSAFE.setMemory(addr, 32, (byte) 0); return addr; } public void disposeBuffer(long addr) { - unsafe.freeMemory(addr); + UNSAFE.freeMemory(addr); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java new file mode 100644 index 00000000000..e7ec7263a4f --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java @@ -0,0 +1,50 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.optimize; + +import org.junit.Test; + +import org.graalvm.compiler.jtt.JTTTest; + +/* + * Tests optimization of float operations. + */ +public class VN_Double03 extends JTTTest { + + public static double test(double arg) { + if (arg == -0.0d) { + return arg; + } + return 0; + } + + @Test + public void run0() throws Throwable { + runTest("test", -0.0d); + } + + @Test + public void run1() throws Throwable { + runTest("test", 0.0d); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java index d42b57e7fe8..e3b767606d5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Monitor_contended01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static class TestClass implements Runnable { boolean started = false; boolean acquired = false; @@ -75,8 +80,9 @@ public final class Monitor_contended01 extends JTTTest { return object.acquired; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java index 8c8978000a8..b1e5fa2a0d7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Monitor_notowner01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + static Object monitor = new Object(); static Object finished = new Object(); @@ -64,8 +69,9 @@ public class Monitor_notowner01 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java index af35abebd89..e53dd0fec5b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Monitorenter01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + static final Object object = new Object(); public static boolean test() { @@ -41,8 +46,9 @@ public final class Monitorenter01 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java index f688227fc39..0377792e964 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Monitorenter02 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + static final Object object = new Object(); public static boolean test() { @@ -45,8 +50,9 @@ public final class Monitorenter02 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java index dc6eae1e25c..d3f4bd78c5c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Object_wait01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -60,23 +65,27 @@ public class Object_wait01 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 3); } - @Test(timeout = 20000) + @Test public void run3() throws Throwable { + initializeForTimeout(); runTest("test", 15); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java index ccd61b3456b..b6771bf1708 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Object_wait02 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -61,18 +66,21 @@ public class Object_wait02 extends JTTTest { return done; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 2); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java index d8376621d5d..d7d2f4f375f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java @@ -24,12 +24,32 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - +import org.graalvm.compiler.core.common.CancellationBailoutException; +import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.nodes.Cancellable; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; + +import jdk.vm.ci.meta.ResolvedJavaMethod; public class Object_wait03 extends JTTTest { + /** + * Timeout for compilation. + */ + static final long COMPILATION_TIMEOUT_MS = 15_000; + + /** + * Total timeout for compilation and execution of compiled code. + */ + static final long TIMEOUT_MS = COMPILATION_TIMEOUT_MS * 2; + + @Rule public TestRule timeout = new DisableOnDebug(Timeout.millis(TIMEOUT_MS)); + private static class TestClass implements Runnable { @Override public void run() { @@ -67,19 +87,61 @@ public class Object_wait03 extends JTTTest { } } - @Test(timeout = 20000) + static class CompilationTimeout extends Thread implements Cancellable { + boolean timedOut; + final long durationMS; + + CompilationTimeout(long durationMS) { + super("CompilationTimeout-" + durationMS + "ms"); + this.durationMS = durationMS; + setDaemon(true); + start(); + } + + @Override + public void run() { + try { + Thread.sleep(durationMS); + } catch (InterruptedException e) { + } + timedOut = true; + } + + @Override + public boolean isCancelled() { + return timedOut; + } + } + + @Override + protected Cancellable getCancellable(ResolvedJavaMethod method) { + return new CompilationTimeout(COMPILATION_TIMEOUT_MS); + } + + private void run(int i) throws Throwable { + initializeForTimeout(); + try { + runTest("test", i); + } catch (CancellationBailoutException e) { + String message = String.format("Compilation cancelled after " + COMPILATION_TIMEOUT_MS + " ms"); + // For diagnosing expectedly long compilations (GR-3853) + Debug.forceDump(lastCompiledGraph, message); + throw new AssertionError(message, e); + } + } + + @Test public void run0() throws Throwable { - runTest("test", 0); + run(0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { - runTest("test", 1); + run(1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { - runTest("test", 2); + run(2); } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java index 925dada3ef5..315b6b36e6c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Object_wait04 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -71,33 +76,39 @@ public class Object_wait04 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 2); } - @Test(timeout = 20000) + @Test public void run3() throws Throwable { + initializeForTimeout(); runTest("test", 3); } - @Test(timeout = 20000) + @Test public void run4() throws Throwable { + initializeForTimeout(); runTest("test", 4); } - @Test(timeout = 20000) + @Test public void run5() throws Throwable { + initializeForTimeout(); runTest("test", 5); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java index fdb58db5814..ebaba3bbde7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java @@ -24,9 +24,12 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; /** * Inspired by {@code com.sun.media.sound.DirectAudioDevice$DirectDL.drain()}. @@ -36,6 +39,8 @@ import org.graalvm.compiler.jtt.JTTTest; */ public final class SynchronizedLoopExit01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + protected Object object = new Object(); protected volatile boolean drained = false; protected volatile boolean someBoolean = true; @@ -53,8 +58,9 @@ public final class SynchronizedLoopExit01 extends JTTTest { return b; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java index 41edeed4e92..1ac56e82a34 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java @@ -26,14 +26,19 @@ package org.graalvm.compiler.jtt.threads; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; //Test all, mainly monitors public class Thread_isInterrupted02 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static final Object start = new Object(); private static final Object end = new Object(); private static int waitTime; @@ -103,13 +108,15 @@ public class Thread_isInterrupted02 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0, 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1, 500); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java index 6e2b3c291b4..6a31b8b37b4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java @@ -22,9 +22,12 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; /* */ @@ -32,6 +35,8 @@ import org.graalvm.compiler.jtt.JTTTest; // Interrupted while sleeping, throws an interrupted exception public class Thread_isInterrupted03 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + public static boolean test() throws InterruptedException { final Thread1 thread = new Thread1(); thread.start(); @@ -69,8 +74,9 @@ public class Thread_isInterrupted03 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java index 9e70ded4d6b..2174adf6874 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java @@ -22,9 +22,12 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; /* */ @@ -32,6 +35,8 @@ import org.graalvm.compiler.jtt.JTTTest; // Interrupted during wait, with interrupter joining public class Thread_isInterrupted05 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + public static boolean test() throws InterruptedException { final WaitInterruptee waitInterruptee = new WaitInterruptee(); waitInterruptee.start(); @@ -67,8 +72,9 @@ public class Thread_isInterrupted05 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java index 1937618b869..e3e7fbc9b1d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Thread_join01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -47,8 +52,9 @@ public class Thread_join01 extends JTTTest { return cont; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java index 824ecf75b10..431677cc2c6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java @@ -27,12 +27,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Thread_join02 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -54,8 +59,9 @@ public class Thread_join02 extends JTTTest { return cont; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java index 1e815b64c7d..e953dd6bc9a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java @@ -27,12 +27,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Thread_join03 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -51,8 +56,9 @@ public class Thread_join03 extends JTTTest { return cont; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java index e2245488715..baf9199ee70 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java @@ -24,30 +24,38 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Thread_sleep01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + public static boolean test(int i) throws InterruptedException { final long before = System.currentTimeMillis(); Thread.sleep(i); return System.currentTimeMillis() - before >= i; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 10); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 20); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 100); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java index 0c6380150a8..345c28d5a19 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java @@ -24,19 +24,25 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Thread_yield01 extends JTTTest { + @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20)); + public static boolean test() { Thread.yield(); return true; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java index a6c6ffaccf5..e2b6999f873 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java @@ -46,20 +46,20 @@ public final class AArch64AddressValue extends CompositeValue { @Component({OperandFlag.REG, OperandFlag.ILLEGAL}) protected AllocatableValue base; @Component({OperandFlag.REG, OperandFlag.ILLEGAL}) protected AllocatableValue offset; - private final int immediate; + private final int displacement; /** * Whether register offset should be scaled or not. */ - private final boolean scaled; + private final int scaleFactor; private final AddressingMode addressingMode; - public AArch64AddressValue(ValueKind kind, AllocatableValue base, AllocatableValue offset, int immediate, boolean scaled, AddressingMode addressingMode) { + public AArch64AddressValue(ValueKind kind, AllocatableValue base, AllocatableValue offset, int displacement, int scaleFactor, AddressingMode addressingMode) { super(kind); this.base = base; this.offset = offset; - this.immediate = immediate; - this.scaled = scaled; + this.displacement = displacement; + this.scaleFactor = scaleFactor; this.addressingMode = addressingMode; } @@ -79,12 +79,16 @@ public final class AArch64AddressValue extends CompositeValue { return offset; } - public int getImmediate() { - return immediate; + public int getDisplacement() { + return displacement; } public boolean isScaled() { - return scaled; + return scaleFactor != 1; + } + + public int getScaleFactor() { + return scaleFactor; } public AddressingMode getAddressingMode() { @@ -95,7 +99,7 @@ public final class AArch64AddressValue extends CompositeValue { Register baseReg = toRegister(base); Register offsetReg = toRegister(offset); AArch64Assembler.ExtendType extendType = addressingMode == AddressingMode.EXTENDED_REGISTER_OFFSET ? ExtendType.SXTW : null; - return AArch64Address.createAddress(addressingMode, baseReg, offsetReg, immediate, scaled, extendType); + return AArch64Address.createAddress(addressingMode, baseReg, offsetReg, displacement / scaleFactor, isScaled(), extendType); } @Override @@ -103,7 +107,7 @@ public final class AArch64AddressValue extends CompositeValue { AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags); AllocatableValue newOffset = (AllocatableValue) proc.doValue(inst, offset, mode, flags); if (!base.identityEquals(newBase) || !offset.identityEquals(newOffset)) { - return new AArch64AddressValue(getValueKind(), newBase, newOffset, immediate, scaled, addressingMode); + return new AArch64AddressValue(getValueKind(), newBase, newOffset, displacement, scaleFactor, addressingMode); } return this; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java index caf734f88e6..cbe7676a382 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java @@ -51,6 +51,7 @@ public enum AArch64ArithmeticOp { SUB(ARITHMETIC), SUBS(ARITHMETIC), MUL, + MULVS, DIV, SMULH, UMULH, @@ -176,6 +177,14 @@ public enum AArch64ArithmeticOp { assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); masm.sub(size, dst, src, (int) b.asLong()); break; + case ADDS: + assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); + masm.adds(size, dst, src, (int) b.asLong()); + break; + case SUBS: + assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); + masm.subs(size, dst, src, (int) b.asLong()); + break; case AND: // XXX Should this be handled somewhere else? if (size == 32 && b.asLong() == 0xFFFF_FFFFL) { @@ -291,6 +300,9 @@ public enum AArch64ArithmeticOp { case FDIV: masm.fdiv(size, dst, src1, src2); break; + case MULVS: + masm.mulvs(size, dst, src1, src2); + break; default: throw GraalError.shouldNotReachHere("op=" + op.name()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java new file mode 100644 index 00000000000..31476aff584 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java @@ -0,0 +1,235 @@ +/* + * 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.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.AArch64Assembler.ConditionFlag; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; +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 of the same length. If the CPU supports any vector + * instructions specialized code is emitted to leverage these instructions. + */ +@Opcode("ARRAY_EQUALS") +public final class AArch64ArrayEqualsOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64ArrayEqualsOp.class); + + private final JavaKind kind; + private final int arrayBaseOffset; + private final int arrayIndexScale; + + @Def({REG}) protected Value resultValue; + @Alive({REG}) protected Value array1Value; + @Alive({REG}) protected Value array2Value; + @Alive({REG}) protected Value lengthValue; + @Temp({REG}) protected Value temp1; + @Temp({REG}) protected Value temp2; + @Temp({REG}) protected Value temp3; + @Temp({REG}) protected Value temp4; + + public AArch64ArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, Value result, Value array1, Value array2, Value length) { + super(TYPE); + this.kind = kind; + + Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass(); + this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass); + this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass); + + this.resultValue = result; + this.array1Value = array1; + this.array2Value = array2; + this.lengthValue = length; + + // Allocate some temporaries. + this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind())); + this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind())); + this.temp3 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())); + this.temp4 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + Register result = asRegister(resultValue); + Register array1 = asRegister(temp1); + Register array2 = asRegister(temp2); + Register length = asRegister(temp3); + + Label breakLabel = new Label(); + + try (ScratchRegister sc1 = masm.getScratchRegister()) { + Register rscratch1 = sc1.getRegister(); + // Load array base addresses. + masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(asRegister(array1Value), arrayBaseOffset)); + masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(asRegister(array2Value), arrayBaseOffset)); + + // Get array length in bytes. + masm.mov(rscratch1, arrayIndexScale); + masm.smaddl(length, asRegister(lengthValue), rscratch1, zr); + masm.mov(64, result, length); // copy + + emit8ByteCompare(crb, masm, result, array1, array2, length, breakLabel, rscratch1); + emitTailCompares(masm, result, array1, array2, breakLabel, rscratch1); + + // Return: rscratch1 is non-zero iff the arrays differ + masm.bind(breakLabel); + masm.cmp(64, rscratch1, zr); + masm.cset(result, ConditionFlag.EQ); + } + } + + /** + * Vector size used in {@link #emit8ByteCompare}. + */ + private static final int VECTOR_SIZE = 8; + + /** + * Emits code that uses 8-byte vector compares. + * + */ + private void emit8ByteCompare(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, Register array1, Register array2, Register length, Label breakLabel, + Register rscratch1) { + Label loop = new Label(); + Label compareTail = new Label(); + + Register temp = asRegister(temp4); + + masm.and(64, result, result, VECTOR_SIZE - 1); // tail count (in bytes) + masm.ands(64, length, length, ~(VECTOR_SIZE - 1)); // vector count (in bytes) + masm.branchConditionally(ConditionFlag.EQ, compareTail); + + masm.lea(array1, AArch64Address.createRegisterOffsetAddress(array1, length, false)); + masm.lea(array2, AArch64Address.createRegisterOffsetAddress(array2, length, false)); + masm.sub(64, length, zr, length); + + // Align the main loop + masm.align(crb.target.wordSize * 2); + masm.bind(loop); + masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, length, false)); + masm.ldr(64, rscratch1, AArch64Address.createRegisterOffsetAddress(array2, length, false)); + masm.eor(64, rscratch1, temp, rscratch1); + masm.cbnz(64, rscratch1, breakLabel); + masm.add(64, length, length, VECTOR_SIZE); + masm.cbnz(64, length, loop); + + masm.cbz(64, result, breakLabel); + + /* + * Compare the remaining bytes with an unaligned memory load aligned to the end of the + * array. + */ + masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(array1, -VECTOR_SIZE)); + masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(array2, -VECTOR_SIZE)); + masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, result, false)); + masm.ldr(64, rscratch1, AArch64Address.createRegisterOffsetAddress(array2, result, false)); + masm.eor(64, rscratch1, temp, rscratch1); + masm.jmp(breakLabel); + + masm.bind(compareTail); + } + + /** + * Emits code to compare the remaining 1 to 4 bytes. + * + */ + private void emitTailCompares(AArch64MacroAssembler masm, Register result, Register array1, Register array2, Label breakLabel, Register rscratch1) { + Label compare2Bytes = new Label(); + Label compare1Byte = new Label(); + Label end = new Label(); + + Register temp = asRegister(temp4); + + if (kind.getByteCount() <= 4) { + // Compare trailing 4 bytes, if any. + masm.ands(32, zr, result, 4); + masm.branchConditionally(ConditionFlag.EQ, compare2Bytes); + masm.ldr(32, temp, AArch64Address.createPostIndexedImmediateAddress(array1, 4)); + masm.ldr(32, rscratch1, AArch64Address.createPostIndexedImmediateAddress(array2, 4)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + + if (kind.getByteCount() <= 2) { + // Compare trailing 2 bytes, if any. + masm.bind(compare2Bytes); + masm.ands(32, zr, result, 2); + masm.branchConditionally(ConditionFlag.EQ, compare1Byte); + masm.ldr(16, temp, AArch64Address.createPostIndexedImmediateAddress(array1, 2)); + masm.ldr(16, rscratch1, AArch64Address.createPostIndexedImmediateAddress(array2, 2)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + + // The one-byte tail compare is only required for boolean and byte arrays. + if (kind.getByteCount() <= 1) { + // Compare trailing byte, if any. + masm.bind(compare1Byte); + masm.ands(32, zr, result, 1); + masm.branchConditionally(ConditionFlag.EQ, end); + masm.ldr(8, temp, AArch64Address.createBaseRegisterOnlyAddress(array1)); + masm.ldr(8, rscratch1, AArch64Address.createBaseRegisterOnlyAddress(array2)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + } else { + masm.bind(compare1Byte); + } + } else { + masm.bind(compare2Bytes); + } + } + masm.bind(end); + masm.mov(64, rscratch1, zr); + } + + 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); + } + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java index 31b6f4e6edf..45bd9330473 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.AllocatableValue; */ public class AArch64BitManipulationOp extends AArch64LIRInstruction { public enum BitManipulationOpCode { - BSF, + CTZ, BSR, BSWP, CLZ, @@ -62,7 +62,7 @@ public class AArch64BitManipulationOp extends AArch64LIRInstruction { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register dst = asRegister(result); Register src = asRegister(input); - final int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; + final int size = input.getPlatformKind().getSizeInBytes() * Byte.SIZE; switch (opcode) { case CLZ: masm.clz(size, dst, src); @@ -73,9 +73,9 @@ public class AArch64BitManipulationOp extends AArch64LIRInstruction { masm.neg(size, dst, dst); masm.add(size, dst, dst, size - 1); break; - case BSF: - // BSF == CLZ(rev(input)) - masm.rev(size, dst, src); + case CTZ: + // CTZ == CLZ(rbit(input)) + masm.rbit(size, dst, src); masm.clz(size, dst, dst); break; case BSWP: diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java index 115e57882b8..5147d96cfcf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java @@ -24,11 +24,12 @@ package org.graalvm.compiler.lir.aarch64; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class AArch64BlockEndOp extends AbstractBlockEndOp { +public abstract class AArch64BlockEndOp extends LIRInstruction implements BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64BlockEndOp.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java new file mode 100644 index 00000000000..0eae02eae13 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012, 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.lir.aarch64; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; + +@Opcode("BSWAP") +public final class AArch64ByteSwapOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64ByteSwapOp.class); + + @Def({OperandFlag.REG, OperandFlag.HINT}) protected Value result; + @Use protected Value input; + + public AArch64ByteSwapOp(Value result, Value input) { + super(TYPE); + this.result = result; + this.input = input; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + switch ((AArch64Kind) input.getPlatformKind()) { + case DWORD: + masm.rev(32, ValueUtil.asRegister(result), ValueUtil.asRegister(input)); + break; + case QWORD: + masm.rev(64, ValueUtil.asRegister(result), ValueUtil.asRegister(input)); + break; + default: + throw GraalError.shouldNotReachHere(); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java new file mode 100644 index 00000000000..b2fef6e1084 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java @@ -0,0 +1,67 @@ +/* + * 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.lir.aarch64; + +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; + +public final class AArch64CCall extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64CCall.class); + + @Def({REG, ILLEGAL}) protected Value result; + @Use({REG, STACK}) protected Value[] parameters; + @Use({REG}) protected Value functionPtr; + + public AArch64CCall(Value result, Value functionPtr, Value[] parameters) { + super(TYPE); + this.result = result; + this.functionPtr = functionPtr; + this.parameters = parameters; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + directCall(masm); + } + + private void directCall(AArch64MacroAssembler masm) { + Register reg = ValueUtil.asRegister(functionPtr); + masm.blr(reg); + masm.ensureUniquePC(); + } + + @Override + public boolean destroysCallerSavedRegisters() { + return true; + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java index 60a6fc90eba..18c96278670 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java @@ -29,7 +29,7 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.calc.Condition; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java index 9604854e9e9..d06f4ccfa00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java @@ -24,16 +24,17 @@ package org.graalvm.compiler.lir.aarch64; import static jdk.vm.ci.code.ValueUtil.asAllocatableValue; import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import java.util.function.Function; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.PatchLabelKind; import org.graalvm.compiler.code.CompilationResult.JumpTable; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; @@ -234,61 +235,51 @@ public class AArch64ControlFlow { } } - public static class TableSwitchOp extends AArch64BlockEndOp implements StandardOp.BlockEndOp { + public static final class TableSwitchOp extends AArch64BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TableSwitchOp.class); - private final int lowKey; private final LabelRef defaultTarget; private final LabelRef[] targets; - @Alive protected Variable keyValue; - @Temp protected Variable scratchValue; + @Use protected Value index; + @Temp({REG, HINT}) protected Value idxScratch; + @Temp protected Value scratch; - public TableSwitchOp(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Variable key, Variable scratch) { + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Value index, Variable scratch, Variable idxScratch) { super(TYPE); this.lowKey = lowKey; this.defaultTarget = defaultTarget; this.targets = targets; - this.keyValue = key; - this.scratchValue = scratch; + this.index = index; + this.scratch = scratch; + this.idxScratch = idxScratch; } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - Register key = asRegister(keyValue); - Register scratch = asRegister(scratchValue); - if (lowKey != 0) { - if (AArch64MacroAssembler.isArithmeticImmediate(lowKey)) { - masm.sub(32, key, key, lowKey); - } else { - ConstantValue constVal = new ConstantValue(LIRKind.value(AArch64Kind.WORD), JavaConstant.forInt(lowKey)); - AArch64Move.move(crb, masm, scratchValue, constVal); - masm.sub(32, key, key, scratch); - } - } + Register indexReg = asRegister(index, AArch64Kind.DWORD); + Register idxScratchReg = asRegister(idxScratch, AArch64Kind.DWORD); + Register scratchReg = asRegister(scratch, AArch64Kind.QWORD); + + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + masm.sub(32, idxScratchReg, indexReg, lowKey); + masm.cmp(32, idxScratchReg, highKey - lowKey); + + // Jump to default target if index is not within the jump table if (defaultTarget != null) { - // if key is not in table range, jump to default target if it exists. - ConstantValue constVal = new ConstantValue(LIRKind.value(AArch64Kind.WORD), JavaConstant.forInt(targets.length)); - emitCompare(crb, masm, keyValue, scratchValue, constVal); - masm.branchConditionally(AArch64Assembler.ConditionFlag.HS, defaultTarget.label()); + masm.branchConditionally(ConditionFlag.HI, defaultTarget.label()); } - // Load the start address of the jump table - which starts 3 instructions after the adr - // - into scratch. - masm.adr(scratch, 4 * 3); - masm.ldr(32, scratch, AArch64Address.createRegisterOffsetAddress(scratch, key, /* scaled */true)); - masm.jmp(scratch); - int jumpTablePos = masm.position(); + Label jumpTable = new Label(); + masm.adr(scratchReg, jumpTable); + masm.add(64, scratchReg, scratchReg, idxScratchReg, ExtendType.UXTW, 2); + masm.jmp(scratchReg); + masm.bind(jumpTable); // emit jump table entries for (LabelRef target : targets) { - Label label = target.label(); - if (label.isBound()) { - masm.emitInt(target.label().position()); - } else { - label.addPatchAt(masm.position()); - masm.emitInt(PatchLabelKind.JUMP_ADDRESS.encoding); - } + masm.jmp(target.label()); } - JumpTable jt = new JumpTable(jumpTablePos, lowKey, lowKey + targets.length - 1, 4); + JumpTable jt = new JumpTable(jumpTable.position(), lowKey, highKey - 1, 4); crb.compilationResult.addAnnotation(jt); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java index 0fb4e831102..af82e5a0c5c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java @@ -110,6 +110,7 @@ public class AArch64Move { super(TYPE); this.result = result; this.input = input; + assert !(isStackSlot(result) && isStackSlot(input)); } @Override @@ -144,7 +145,7 @@ public class AArch64Move { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register dst = asRegister(result); AArch64Address adr = address.toAddress(); - masm.loadAddress(dst, adr, address.getPlatformKind().getSizeInBytes()); + masm.loadAddress(dst, adr, address.getScaleFactor()); } } @@ -182,9 +183,11 @@ public class AArch64Move { @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - AArch64Address address = (AArch64Address) crb.asAddress(slot); - PlatformKind kind = AArch64Kind.QWORD; - masm.loadAddress(asRegister(result, kind), address, kind.getSizeInBytes()); + try (ScratchRegister addrReg = masm.getScratchRegister()) { + AArch64Address address = loadStackSlotAddress(crb, masm, (StackSlot) slot, addrReg.getRegister()); + PlatformKind kind = AArch64Kind.QWORD; + masm.loadAddress(asRegister(result, kind), address, kind.getSizeInBytes()); + } } } @@ -238,8 +241,8 @@ public class AArch64Move { @Override public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { - int immediate = addressValue.getImmediate(); - if (state == null && value.equals(addressValue.getBase()) && addressValue.getOffset().equals(Value.ILLEGAL) && immediate >= 0 && immediate < implicitNullCheckLimit) { + int displacement = addressValue.getDisplacement(); + if (state == null && value.equals(addressValue.getBase()) && addressValue.getOffset().equals(Value.ILLEGAL) && displacement >= 0 && displacement < implicitNullCheckLimit) { state = nullCheckState; return true; } @@ -265,8 +268,7 @@ public class AArch64Move { int destSize = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; int srcSize = kind.getSizeInBytes() * Byte.SIZE; if (kind.isInteger()) { - // TODO How to load unsigned chars without the necessary information? - masm.ldrs(destSize, srcSize, dst, address); + masm.ldr(srcSize, dst, address); } else { assert srcSize == destSize; masm.fldr(srcSize, dst, address); @@ -412,6 +414,8 @@ public class AArch64Move { } else if (isStackSlot(input)) { if (isRegister(result)) { stack2reg(crb, masm, result, asAllocatableValue(input)); + } else if (isStackSlot(result)) { + emitStackMove(crb, masm, result, input); } else { throw GraalError.shouldNotReachHere(); } @@ -426,6 +430,24 @@ public class AArch64Move { } } + private static void emitStackMove(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, Value input) { + try (ScratchRegister r1 = masm.getScratchRegister()) { + try (ScratchRegister r2 = masm.getScratchRegister()) { + Register rscratch1 = r1.getRegister(); + Register rscratch2 = r2.getRegister(); + PlatformKind kind = input.getPlatformKind(); + final int size = kind.getSizeInBytes() <= 4 ? 32 : 64; + + // Always perform stack -> stack copies through integer registers + crb.blockComment("[stack -> stack copy]"); + AArch64Address src = loadStackSlotAddress(crb, masm, asStackSlot(input), rscratch2); + masm.ldr(size, rscratch1, src); + AArch64Address dst = loadStackSlotAddress(crb, masm, asStackSlot(result), rscratch2); + masm.str(size, rscratch1, dst); + } + } + } + private static void reg2reg(@SuppressWarnings("unused") CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { Register dst = asRegister(result); Register src = asRegister(input); @@ -524,15 +546,17 @@ public class AArch64Move { } private static void const2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, Value result, JavaConstant constant) { - if (constant.isDefaultForKind() || constant.isNull()) { - AArch64Address resultAddress = (AArch64Address) crb.asAddress(result); - emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, zr.asValue(LIRKind.combine(result))); - } else { - try (ScratchRegister sc = masm.getScratchRegister()) { - Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.combine(result)); - const2reg(crb, masm, scratchRegisterValue, constant); - AArch64Address resultAddress = (AArch64Address) crb.asAddress(result); - emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, scratchRegisterValue); + try (ScratchRegister addrReg = masm.getScratchRegister()) { + StackSlot slot = (StackSlot) result; + AArch64Address resultAddress = loadStackSlotAddress(crb, masm, slot, addrReg.getRegister()); + if (constant.isDefaultForKind() || constant.isNull()) { + emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, zr.asValue(LIRKind.combine(result))); + } else { + try (ScratchRegister sc = masm.getScratchRegister()) { + Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.combine(result)); + const2reg(crb, masm, scratchRegisterValue, constant); + emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, scratchRegisterValue); + } } } } @@ -552,9 +576,13 @@ public class AArch64Move { * @return AArch64Address of given StackSlot. Uses scratch register if necessary to do so. */ private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, AllocatableValue scratch) { + Register scratchReg = Value.ILLEGAL.equals(scratch) ? zr : asRegister(scratch); + return loadStackSlotAddress(crb, masm, slot, scratchReg); + } + + private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, Register scratchReg) { int displacement = crb.frameMap.offsetForStackSlot(slot); int transferSize = slot.getPlatformKind().getSizeInBytes(); - Register scratchReg = Value.ILLEGAL.equals(scratch) ? zr : asRegister(scratch); return masm.makeAddress(sp, displacement, scratchReg, transferSize, /* allowOverwrite */false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java index 47f4d99ca91..49a7b278757 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java @@ -54,6 +54,6 @@ public class AArch64SignExtendOp extends AArch64LIRInstruction { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register result = asRegister(resultValue); Register input = asRegister(inputValue); - masm.sxt(toBits, fromBits, result, input); + masm.sxt(toBits <= 32 ? 32 : 64, fromBits, result, input); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java new file mode 100644 index 00000000000..a5af104860c --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java @@ -0,0 +1,95 @@ +/* + * 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.lir.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +/** + * AARCH64 LIR instructions that have one input and one output. + */ +public class AArch64Unary { + + /** + * Instruction with a {@link AArch64AddressValue memory} operand. + */ + public static class MemoryOp extends AArch64LIRInstruction implements ImplicitNullCheck { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MemoryOp.class); + + private final boolean isSigned; + + @Def({REG}) protected AllocatableValue result; + @Use({COMPOSITE}) protected AArch64AddressValue input; + + @State protected LIRFrameState state; + + private int targetSize; + private int srcSize; + + public MemoryOp(boolean isSigned, int targetSize, int srcSize, AllocatableValue result, AArch64AddressValue input, LIRFrameState state) { + super(TYPE); + this.targetSize = targetSize; + this.srcSize = srcSize; + this.isSigned = isSigned; + this.result = result; + this.input = input; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } + AArch64Address address = input.toAddress(); + Register dst = asRegister(result); + if (isSigned) { + masm.ldrs(targetSize, srcSize, dst, address); + } else { + masm.ldr(srcSize, dst, address); + } + } + + @Override + public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { + int displacement = input.getDisplacement(); + if (state == null && value.equals(input.getBase()) && input.getOffset().equals(Value.ILLEGAL) && displacement >= 0 && displacement < implicitNullCheckLimit) { + state = nullCheckState; + return true; + } + return false; + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java index d67920fb023..f3f8a92f6a6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java @@ -65,6 +65,14 @@ public final class AMD64AddressValue extends CompositeValue { assert scale != null; } + public AllocatableValue getBase() { + return base; + } + + public AllocatableValue getIndex() { + return index; + } + @Override public CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags); @@ -81,6 +89,10 @@ public final class AMD64AddressValue extends CompositeValue { proc.visitValue(inst, index, mode, flags); } + public AMD64AddressValue withKind(ValueKind newKind) { + return new AMD64AddressValue(newKind, base, index, scale, displacement); + } + private static Register toRegister(AllocatableValue value) { if (value.equals(Value.ILLEGAL)) { return Register.None; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java index cff91a19bac..d5419f74c30 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java @@ -32,7 +32,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java index 8669c5217de..5f8f04abc2b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java @@ -30,7 +30,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java index 4f09ee0292d..def894caee8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java @@ -23,11 +23,12 @@ package org.graalvm.compiler.lir.amd64; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class AMD64BlockEndOp extends AbstractBlockEndOp { +public abstract class AMD64BlockEndOp extends LIRInstruction implements BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64BlockEndOp.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java index dbddbcb191c..348d22eda3c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java @@ -31,7 +31,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java index 67bcfe63357..174305a29ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.lir.amd64; import static jdk.vm.ci.code.ValueUtil.asStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.framemap.FrameMap; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java index e2bdfd3f4df..9692e1bfd00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java @@ -35,7 +35,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java index f4758ce3d31..68e80e0a95a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java @@ -27,8 +27,6 @@ import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isStackSlot; import java.util.Arrays; -import java.util.Set; - import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LIRValueUtil; @@ -36,6 +34,7 @@ import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; @@ -61,16 +60,16 @@ public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveReg @Def(STACK) protected final AllocatableValue[] slots; /** - * Specifies if {@link #remove(Set)} should have an effect. + * Specifies if {@link #remove(EconomicSet)} should have an effect. */ protected final boolean supportsRemove; /** * * @param savedRegisters the registers saved by this operation which may be subject to - * {@linkplain #remove(Set) pruning} + * {@linkplain #remove(EconomicSet) pruning} * @param savedRegisterLocations the slots to which the registers are saved - * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned} + * @param supportsRemove determines if registers can be {@linkplain #remove(EconomicSet) pruned} */ public AMD64SaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { this(TYPE, savedRegisters, savedRegisterLocations, supportsRemove); @@ -108,14 +107,14 @@ public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveReg } @Override - public int remove(Set doNotSave) { + public int remove(EconomicSet doNotSave) { if (!supportsRemove) { throw new UnsupportedOperationException(); } return prune(doNotSave, savedRegisters); } - static int prune(Set toRemove, Register[] registers) { + static int prune(EconomicSet toRemove, Register[] registers) { int pruned = 0; for (int i = 0; i < registers.length; i++) { if (registers[i] != null) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java new file mode 100644 index 00000000000..aeb736b5588 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java @@ -0,0 +1,102 @@ +/* + * 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.lir.amd64; + +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +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.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64.CPUFeature; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.Value; + +/** + */ +@Opcode("AMD64_STRING_INDEX_OF") +public final class AMD64StringIndexOfOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64StringIndexOfOp.class); + + @Def({REG}) protected Value resultValue; + @Alive({REG}) protected Value charPtr1Value; + @Alive({REG}) protected Value charPtr2Value; + @Use({REG}) protected RegisterValue cnt1Value; + @Temp({REG}) protected RegisterValue cnt1ValueT; + @Use({REG}) protected RegisterValue cnt2Value; + @Temp({REG}) protected RegisterValue cnt2ValueT; + @Temp({REG}) protected Value temp1; + @Temp({REG, ILLEGAL}) protected Value vectorTemp1; + + private final int intCnt2; + + private final int vmPageSize; + + public AMD64StringIndexOfOp(LIRGeneratorTool tool, Value result, Value charPtr1, Value charPtr2, RegisterValue cnt1, RegisterValue cnt2, RegisterValue temp1, RegisterValue vectorTemp1, + int intCnt2, int vmPageSize) { + super(TYPE); + assert ((AMD64) tool.target().arch).getFeatures().contains(CPUFeature.SSE4_2); + resultValue = result; + charPtr1Value = charPtr1; + charPtr2Value = charPtr2; + /* + * The count values are inputs but are also killed like temporaries so need both Use and + * Temp annotations, which will only work with fixed registers. + */ + cnt1Value = cnt1; + cnt1ValueT = cnt1; + cnt2Value = cnt2; + cnt2ValueT = cnt2; + assert asRegister(cnt1).equals(rdx) && asRegister(cnt2).equals(rax) && asRegister(temp1).equals(rcx) : "fixed register usage required"; + + this.temp1 = temp1; + this.vectorTemp1 = vectorTemp1; + this.intCnt2 = intCnt2; + this.vmPageSize = vmPageSize; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + Register charPtr1 = asRegister(charPtr1Value); + Register charPtr2 = asRegister(charPtr2Value); + Register cnt1 = asRegister(cnt1Value); + Register cnt2 = asRegister(cnt2Value); + Register result = asRegister(resultValue); + Register vec = asRegister(vectorTemp1); + Register tmp = asRegister(temp1); + if (intCnt2 >= 8) { + masm.stringIndexofC8(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp); + } else { + masm.stringIndexOf(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp, vmPageSize); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java index 1345b49e2e2..134abcbb7ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java @@ -24,14 +24,13 @@ package org.graalvm.compiler.lir.amd64; import static org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp.prune; -import java.util.Set; - import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; @@ -76,7 +75,7 @@ public final class AMD64ZapRegistersOp extends AMD64LIRInstruction implements Sa } @Override - public int remove(Set doNotSave) { + public int remove(EconomicSet doNotSave) { return prune(doNotSave, zappedRegisters); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java index 3eee2c46aa3..2d8cff20468 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64StackMove; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; -import org.graalvm.compiler.options.NestedBooleanOptionValue; +import org.graalvm.compiler.options.NestedBooleanOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; @@ -58,7 +58,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase public static class Options { // @formatter:off @Option(help = "", type = OptionType.Debug) - public static final NestedBooleanOptionValue LIROptStackMoveOptimizer = new NestedBooleanOptionValue(LIROptimization, true); + public static final NestedBooleanOptionKey LIROptStackMoveOptimizer = new NestedBooleanOptionKey(LIROptimization, true); // @formatter:on } @@ -68,7 +68,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { LIR lir = lirGenRes.getLIR(); for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { - List instructions = lir.getLIRforBlock(block); + ArrayList instructions = lir.getLIRforBlock(block); new Closure().process(instructions); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java index 39e4c7f8c79..0a4e15e2481 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java @@ -40,7 +40,6 @@ import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -191,9 +190,7 @@ public abstract class LIRTest extends JTTTest { }; @Override - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); - + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { Class c = getClass(); for (Method m : c.getMethods()) { if (m.getAnnotation(LIRIntrinsic.class) != null) { @@ -215,7 +212,7 @@ public abstract class LIRTest extends JTTTest { }; invocationPlugins.register(outputPlugin, LIRTest.class, "getOutput", new Class[]{LIRTestSpecification.class, String.class, Object.class}); invocationPlugins.register(outputPlugin, LIRTest.class, "getOutput", new Class[]{LIRTestSpecification.class, String.class, int.class}); - return super.editGraphBuilderConfiguration(conf); + super.registerInvocationPlugins(invocationPlugins); } @SuppressWarnings("unused") diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java index 2f6cc407e45..f9e8d959aba 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java @@ -22,17 +22,18 @@ */ package org.graalvm.compiler.lir.jtt; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugConfigScope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -76,12 +77,15 @@ public class SPARCBranchBailoutTest extends LIRTest { return GraalDirectives.opaque(res); } + @SuppressWarnings("try") @Test public void testBailoutOnBranchOverflow() throws Throwable { Assume.assumeTrue(getBackend().getTarget().arch instanceof SPARC); ResolvedJavaMethod m = getResolvedJavaMethod("testBranch"); try { - compile(m, null); + try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) { + compile(m, null); + } } catch (GraalError e) { Assert.assertEquals(PermanentBailoutException.class, e.getCause().getClass()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java index 44edf5a51c4..97b85ccd987 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -71,7 +71,7 @@ public class SPARCArithmetic { public static final SizeEstimate SIZE = SizeEstimate.create(5); @Opcode private final FloatConvert opcode; - @Def({REG, HINT}) protected Value result; + @Def({REG, HINT}) protected AllocatableValue result; @Use({REG}) protected Value x; public enum FloatConvert { @@ -81,7 +81,7 @@ public class SPARCArithmetic { D2L } - public FloatConvertOp(FloatConvert opcode, Value x, Value result) { + public FloatConvertOp(FloatConvert opcode, Value x, AllocatableValue result) { super(TYPE, SIZE); this.opcode = opcode; this.x = x; @@ -138,11 +138,11 @@ public class SPARCArithmetic { public static final SizeEstimate SIZE = SizeEstimate.create(4); @Opcode private final Rem opcode; - @Def({REG}) protected Value result; + @Def({REG}) protected AllocatableValue result; @Alive({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; - @Temp({REG}) protected Value scratch1; - @Temp({REG}) protected Value scratch2; + @Temp({REG}) protected AllocatableValue scratch1; + @Temp({REG}) protected AllocatableValue scratch2; @State protected LIRFrameState state; public enum Rem { @@ -150,7 +150,7 @@ public class SPARCArithmetic { LUREM } - public RemOp(Rem opcode, Value result, Value x, Value y, Value scratch1, Value scratch2, LIRFrameState state) { + public RemOp(Rem opcode, AllocatableValue result, Value x, Value y, AllocatableValue scratch1, AllocatableValue scratch2, LIRFrameState state) { super(TYPE, SIZE); this.opcode = opcode; this.result = result; @@ -170,7 +170,9 @@ public class SPARCArithmetic { assert !y.equals(scratch1); switch (opcode) { case LUREM: - crb.recordImplicitException(masm.position(), state); + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } masm.udivx(asRegister(x, XWORD), crb.asIntConst(y), asRegister(scratch1, XWORD)); masm.mulx(asRegister(scratch1, XWORD), crb.asIntConst(y), asRegister(scratch2, XWORD)); getDelayedControlTransfer().emitControlTransfer(crb, masm); @@ -192,7 +194,9 @@ public class SPARCArithmetic { } assert !asRegister(xLeft, XWORD).equals(asRegister(scratch1, XWORD)); assert !asRegister(y, XWORD).equals(asRegister(scratch1, XWORD)); - crb.recordImplicitException(masm.position(), state); + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } masm.udivx(asRegister(xLeft, XWORD), asRegister(y, XWORD), asRegister(scratch1, XWORD)); masm.mulx(asRegister(scratch1, XWORD), asRegister(y, XWORD), asRegister(scratch1, XWORD)); getDelayedControlTransfer().emitControlTransfer(crb, masm); @@ -203,7 +207,9 @@ public class SPARCArithmetic { assert !asRegister(result, WORD).equals(asRegister(scratch2, WORD)); masm.srl(asRegister(x, WORD), 0, asRegister(scratch1, WORD)); masm.srl(asRegister(y, WORD), 0, asRegister(result, WORD)); - crb.recordImplicitException(masm.position(), state); + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } masm.udivx(asRegister(scratch1, WORD), asRegister(result, WORD), asRegister(scratch2, WORD)); masm.mulx(asRegister(scratch2, WORD), asRegister(result, WORD), asRegister(result, WORD)); getDelayedControlTransfer().emitControlTransfer(crb, masm); @@ -221,11 +227,11 @@ public class SPARCArithmetic { public static final class SPARCIMulccOp extends SPARCLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCIMulccOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(10); - @Def({REG}) protected Value result; - @Alive({REG}) protected Value x; - @Alive({REG}) protected Value y; + @Def({REG}) protected AllocatableValue result; + @Alive({REG}) protected AllocatableValue x; + @Alive({REG}) protected AllocatableValue y; - public SPARCIMulccOp(Value result, Value x, Value y) { + public SPARCIMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y) { super(TYPE, SIZE); this.result = result; this.x = x; @@ -258,13 +264,13 @@ public class SPARCArithmetic { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCLMulccOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(13); - @Def({REG}) protected Value result; - @Alive({REG}) protected Value x; - @Alive({REG}) protected Value y; - @Temp({REG}) protected Value scratch1; - @Temp({REG}) protected Value scratch2; + @Def({REG}) protected AllocatableValue result; + @Alive({REG}) protected AllocatableValue x; + @Alive({REG}) protected AllocatableValue y; + @Temp({REG}) protected AllocatableValue scratch1; + @Temp({REG}) protected AllocatableValue scratch2; - public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) { + public SPARCLMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y, LIRGeneratorTool gen) { super(TYPE, SIZE); this.result = result; this.x = x; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java index 1a0be8840e5..78ef442a395 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.g0; +import static jdk.vm.ci.sparc.SPARCKind.WORD; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; @@ -32,9 +35,6 @@ import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Equal; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Less; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARCKind.WORD; import java.lang.reflect.Array; import java.lang.reflect.Field; @@ -49,8 +49,8 @@ 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.AllocatableValue; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; import sun.misc.Unsafe; @@ -66,17 +66,17 @@ public final class SPARCArrayEqualsOp extends SPARCLIRInstruction { private final int arrayBaseOffset; private final int arrayIndexScale; - @Def({REG}) protected Value resultValue; - @Alive({REG}) protected Value array1Value; - @Alive({REG}) protected Value array2Value; - @Alive({REG}) protected Value lengthValue; - @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; + @Def({REG}) protected AllocatableValue resultValue; + @Alive({REG}) protected AllocatableValue array1Value; + @Alive({REG}) protected AllocatableValue array2Value; + @Alive({REG}) protected AllocatableValue lengthValue; + @Temp({REG}) protected AllocatableValue temp1; + @Temp({REG}) protected AllocatableValue temp2; + @Temp({REG}) protected AllocatableValue temp3; + @Temp({REG}) protected AllocatableValue temp4; + @Temp({REG}) protected AllocatableValue temp5; - public SPARCArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, Value result, Value array1, Value array2, Value length) { + public SPARCArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, AllocatableValue result, AllocatableValue array1, AllocatableValue array2, AllocatableValue length) { super(TYPE, SIZE); this.kind = kind; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java index 1221cebba46..e296e65396e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.lir.sparc; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.sparc.SPARC.g0; import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.core.common.LIRKind; @@ -40,7 +40,6 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.PlatformKind; -import jdk.vm.ci.meta.Value; public final class SPARCBitManipulationOp extends SPARCLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBitManipulationOp.class); @@ -60,7 +59,7 @@ public final class SPARCBitManipulationOp extends SPARCLIRInstruction { @Opcode private final IntrinsicOpcode opcode; @Def protected AllocatableValue result; @Alive({REG}) protected AllocatableValue input; - @Temp({REG}) protected Value scratch; + @Temp({REG}) protected AllocatableValue scratch; public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input, LIRGeneratorTool gen) { super(TYPE, opcode.size); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java index ed551fce119..71617b952d0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java @@ -23,11 +23,12 @@ package org.graalvm.compiler.lir.sparc; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class SPARCBlockEndOp extends AbstractBlockEndOp implements SPARCLIRInstructionMixin { +public abstract class SPARCBlockEndOp extends LIRInstruction implements BlockEndOp, SPARCLIRInstructionMixin { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBlockEndOp.class); private final SPARCLIRInstructionMixinStore store; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java index 4679dacc6c1..e497ef90232 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARCKind.WORD; +import static jdk.vm.ci.sparc.SPARCKind.XWORD; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARCKind.WORD; -import static jdk.vm.ci.sparc.SPARCKind.XWORD; import org.graalvm.compiler.asm.sparc.SPARCAddress; import org.graalvm.compiler.asm.sparc.SPARCAssembler.Asi; @@ -43,19 +43,18 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.ValueUtil; import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; @Opcode("BSWAP") public final class SPARCByteSwapOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCByteSwapOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(3); - @Def({REG, HINT}) protected Value result; - @Use({REG}) protected Value input; - @Temp({REG}) protected Value tempIndex; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue input; + @Temp({REG}) protected AllocatableValue tempIndex; @Use({STACK, UNINITIALIZED}) protected AllocatableValue tmpSlot; - public SPARCByteSwapOp(LIRGeneratorTool tool, Value result, Value input) { + public SPARCByteSwapOp(LIRGeneratorTool tool, AllocatableValue result, AllocatableValue input) { super(TYPE, SIZE); this.result = result; this.input = input; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java index a7823bb46ba..ec96b34ba4e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -22,6 +22,11 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.CPU; +import static jdk.vm.ci.sparc.SPARC.g0; +import static jdk.vm.ci.sparc.SPARCKind.WORD; +import static jdk.vm.ci.sparc.SPARCKind.XWORD; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CBCOND; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.FBPCC; @@ -68,22 +73,14 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static org.graalvm.compiler.lir.sparc.SPARCMove.const2reg; import static org.graalvm.compiler.lir.sparc.SPARCOP3Op.emitOp3; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.CPU; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARCKind.WORD; -import static jdk.vm.ci.sparc.SPARCKind.XWORD; import java.util.ArrayList; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.sparc.SPARCAssembler; import org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict; import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; @@ -101,6 +98,8 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -144,7 +143,7 @@ public class SPARCControlFlow { public static final SizeEstimate SIZE = SizeEstimate.create(3); static final EnumSet SUPPORTED_KINDS = EnumSet.of(XWORD, WORD); - @Use({REG}) protected Value x; + @Use({REG}) protected AllocatableValue x; @Use({REG, CONST}) protected Value y; private ConditionFlag conditionFlag; protected final LabelRef trueDestination; @@ -157,8 +156,10 @@ public class SPARCControlFlow { private int delaySlotPosition = -1; private double trueDestinationProbability; - public CompareBranchOp(Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, double trueDestinationProbability) { + public CompareBranchOp(AllocatableValue x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, + double trueDestinationProbability) { super(TYPE, SIZE); + assert x.getPlatformKind() == y.getPlatformKind() : String.format("PlatformKind of x must match PlatformKind of y. %s!=%s", x.getPlatformKind(), y.getPlatformKind()); this.x = x; this.y = y; this.trueDestination = trueDestination; @@ -250,6 +251,7 @@ public class SPARCControlFlow { * @return true if the branch could be emitted */ private boolean emitShortCompareBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + boolean isLong = kind == SPARCKind.XWORD; ConditionFlag actualConditionFlag = conditionFlag; Label actualTrueTarget = trueDestination.label(); Label actualFalseTarget = falseDestination.label(); @@ -274,7 +276,7 @@ public class SPARCControlFlow { actualFalseTarget = tmpTarget; } } - emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag); + emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag, isLong); if (needJump) { masm.jmp(actualFalseTarget); masm.nop(); @@ -282,16 +284,24 @@ public class SPARCControlFlow { return true; } - private void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag) { + private static void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag, boolean isLong) { PlatformKind xKind = actualX.getPlatformKind(); - boolean isLong = kind == SPARCKind.XWORD; + Register rs1 = asRegister(actualX, xKind); if (isJavaConstant(actualY)) { JavaConstant c = asJavaConstant(actualY); long constantY = c.isNull() ? 0 : c.asLong(); - assert NumUtil.isInt(constantY); - CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), (int) constantY, actualTrueTarget); + try (ScratchRegister scratch = masm.getScratchRegister()) { + if (SPARCMacroAssembler.isSimm5(constantY)) { + CBCOND.emit(masm, cFlag, isLong, rs1, (int) constantY, actualTrueTarget); + } else { // !simm5 + Register rs2 = scratch.getRegister(); + masm.setx(constantY, rs2, false); + CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget); + } + } } else { - CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), asRegister(actualY, xKind), actualTrueTarget); + Register rs2 = asRegister(actualY, xKind); + CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget); } } @@ -426,15 +436,16 @@ public class SPARCControlFlow { @Alive({REG, ILLEGAL}) protected Value constantTableBase; @Temp({REG}) protected Value scratch; protected final SwitchStrategy strategy; - private final Map labelHints; + private final EconomicMap labelHints; private final List