This commit is contained in:
Jesper Wilhelmsson 2015-11-05 19:31:57 +01:00
commit 1a5787d42e
172 changed files with 9885 additions and 597 deletions

View file

@ -331,3 +331,4 @@ f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83
7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86 7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86
1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87 1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87
16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88 16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88
4a0312f2894bcbe1fd20266c8fda8d983bd2fcf6 jdk9-b89

View file

@ -331,3 +331,4 @@ ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83
2aa1daf98d3e2ee37f20f6858c53cc37020f6937 jdk9-b86 2aa1daf98d3e2ee37f20f6858c53cc37020f6937 jdk9-b86
fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87 fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87
0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88 0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88
895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89

View file

@ -331,3 +331,4 @@ df70bb200356fec686681f0295c50cc3ed43c3b3 jdk9-b84
0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86 0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86
a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87 a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87
00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88 00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88
c847a53b38d2fffb87afc483c74db05eced9b4f4 jdk9-b89

View file

@ -491,3 +491,4 @@ e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86 1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86
d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87 d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87
bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88 bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88
20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89

View file

@ -97,6 +97,7 @@ else
# prints the numbers (e.g. "2.95", "3.2.1") # prints the numbers (e.g. "2.95", "3.2.1")
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1) CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2) CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
endif endif
ifeq ($(USE_CLANG), true) ifeq ($(USE_CLANG), true)
@ -333,6 +334,10 @@ ifeq ($(USE_CLANG), true)
$(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)") $(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
endif endif
else else
# Do not allow GCC 4.1.1
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
$(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
endif
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation. # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1) ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT) OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)

View file

@ -109,7 +109,11 @@ $(GENSRC_DIR)/_providers_converted: $(GENSRC_DIR)/_gensrc_proc_done
($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \ ($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
for i in $$($(LS)); do \ for i in $$($(LS)); do \
c=$$($(CAT) $$i | $(TR) -d '\n\r'); \ c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
$(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c; \ $(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c.tmp; \
done)
($(CD) $(GENSRC_DIR)/META-INF/services && \
for i in $$($(LS) *.tmp); do \
$(MV) $$i $${i%.tmp}; \
done) done)
$(TOUCH) $@ $(TOUCH) $@

View file

@ -60,6 +60,7 @@ else
# prints the numbers (e.g. "2.95", "3.2.1") # prints the numbers (e.g. "2.95", "3.2.1")
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1) CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2) CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
endif endif
ifeq ($(USE_CLANG), true) ifeq ($(USE_CLANG), true)
@ -266,6 +267,10 @@ ifeq ($(USE_CLANG), true)
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
endif endif
else else
# Do not allow GCC 4.1.1
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
$(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
endif
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation. # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1) ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT) OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)

View file

@ -39,6 +39,7 @@ Compiler = gcc
# prints the numbers (e.g. "2.95", "3.2.1") # prints the numbers (e.g. "2.95", "3.2.1")
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1) CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2) CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
# Check for the versions of C++ and C compilers ($CXX and $CC) used. # Check for the versions of C++ and C compilers ($CXX and $CC) used.
@ -160,6 +161,10 @@ ifeq ($(USE_CLANG), true)
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
endif endif
else else
# Do not allow GCC 4.1.1
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
$(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
endif
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation. # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1) ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT) OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)

View file

@ -59,9 +59,9 @@ define_pd_global(intx, InlineFrequencyCount, 100);
#define DEFAULT_STACK_RED_PAGES (1) #define DEFAULT_STACK_RED_PAGES (1)
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5)) #define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES #define MIN_STACK_YELLOW_PAGES 1
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES #define MIN_STACK_RED_PAGES 1
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES #define MIN_STACK_SHADOW_PAGES 1
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES); define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES); define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);

View file

@ -1777,7 +1777,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
const Register obj_reg = r19; // Will contain the oop const Register obj_reg = r19; // Will contain the oop
const Register lock_reg = r13; // Address of compiler lock object (BasicLock) const Register lock_reg = r13; // Address of compiler lock object (BasicLock)
const Register old_hdr = r13; // value of old header at unlock time const Register old_hdr = r13; // value of old header at unlock time
const Register tmp = c_rarg3; const Register tmp = lr;
Label slow_path_lock; Label slow_path_lock;
Label lock_done; Label lock_done;

View file

@ -1539,7 +1539,6 @@ void Assembler::cmpl(Register dst, Register src) {
emit_arith(0x3B, 0xC0, dst, src); emit_arith(0x3B, 0xC0, dst, src);
} }
void Assembler::cmpl(Register dst, Address src) { void Assembler::cmpl(Register dst, Address src) {
InstructionMark im(this); InstructionMark im(this);
prefix(src, dst); prefix(src, dst);
@ -2125,6 +2124,16 @@ void Assembler::movb(Register dst, Address src) {
emit_operand(dst, src); emit_operand(dst, src);
} }
void Assembler::movddup(XMMRegister dst, XMMRegister src) {
_instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse3(), ""));
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F2, /* no_mask_reg */ false, VEX_OPCODE_0F,
/* rex_w */ VM_Version::supports_evex(), AVX_128bit, /* legacy_mode */ false);
emit_int8(0x12);
emit_int8(0xC0 | encode);
}
void Assembler::kmovql(KRegister dst, KRegister src) { void Assembler::kmovql(KRegister dst, KRegister src) {
NOT_LP64(assert(VM_Version::supports_evex(), "")); NOT_LP64(assert(VM_Version::supports_evex(), ""));
int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE, int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
@ -3403,6 +3412,20 @@ void Assembler::rcll(Register dst, int imm8) {
} }
} }
void Assembler::rcpps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x53);
emit_int8(0xC0 | encode);
}
void Assembler::rcpss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x53);
emit_int8(0xC0 | encode);
}
void Assembler::rdtsc() { void Assembler::rdtsc() {
emit_int8((unsigned char)0x0F); emit_int8((unsigned char)0x0F);
emit_int8((unsigned char)0x31); emit_int8((unsigned char)0x31);
@ -6326,6 +6349,26 @@ void Assembler::emit_vex_arith_q(int opcode, XMMRegister dst, XMMRegister nds, X
emit_int8((unsigned char)(0xC0 | encode)); emit_int8((unsigned char)(0xC0 | encode));
} }
void Assembler::cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len) {
assert(VM_Version::supports_avx(), "");
assert(!VM_Version::supports_evex(), "");
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F, /* no_mask_reg */ false);
emit_int8((unsigned char)0xC2);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8((unsigned char)(0xF & cop));
}
void Assembler::vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len) {
assert(VM_Version::supports_avx(), "");
assert(!VM_Version::supports_evex(), "");
int encode = vex_prefix_and_encode(dst, nds, src1, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A, /* no_mask_reg */ false);
emit_int8((unsigned char)0x4B);
emit_int8((unsigned char)(0xC0 | encode));
int src2_enc = src2->encoding();
emit_int8((unsigned char)(0xF0 & src2_enc<<4));
}
#ifndef _LP64 #ifndef _LP64
void Assembler::incl(Register dst) { void Assembler::incl(Register dst) {

View file

@ -1504,6 +1504,8 @@ private:
void movb(Address dst, int imm8); void movb(Address dst, int imm8);
void movb(Register dst, Address src); void movb(Register dst, Address src);
void movddup(XMMRegister dst, XMMRegister src);
void kmovql(KRegister dst, KRegister src); void kmovql(KRegister dst, KRegister src);
void kmovql(KRegister dst, Register src); void kmovql(KRegister dst, Register src);
void kmovdl(KRegister dst, Register src); void kmovdl(KRegister dst, Register src);
@ -1768,6 +1770,10 @@ private:
void rcrq(Register dst, int imm8); void rcrq(Register dst, int imm8);
void rcpps(XMMRegister dst, XMMRegister src);
void rcpss(XMMRegister dst, XMMRegister src);
void rdtsc(); void rdtsc();
void ret(int imm16); void ret(int imm16);
@ -2141,6 +2147,11 @@ private:
// runtime code and native libraries. // runtime code and native libraries.
void vzeroupper(); void vzeroupper();
// AVX support for vectorized conditional move (double). The following two instructions used only coupled.
void cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len);
void vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len);
protected: protected:
// Next instructions require address alignment 16 bytes SSE mode. // Next instructions require address alignment 16 bytes SSE mode.
// They should be called only from corresponding MacroAssembler instructions. // They should be called only from corresponding MacroAssembler instructions.

View file

@ -2441,7 +2441,6 @@ void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, L
} else if (value->is_double_fpu()) { } else if (value->is_double_fpu()) {
assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS"); assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS");
switch(code) { switch(code) {
case lir_log : __ flog() ; break;
case lir_log10 : __ flog10() ; break; case lir_log10 : __ flog10() ; break;
case lir_abs : __ fabs() ; break; case lir_abs : __ fabs() ; break;
case lir_sqrt : __ fsqrt(); break; case lir_sqrt : __ fsqrt(); break;

View file

@ -809,8 +809,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type"); assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
if (x->id() == vmIntrinsics::_dexp) { if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog) {
do_ExpIntrinsic(x); do_LibmIntrinsic(x);
return; return;
} }
@ -822,7 +822,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
case vmIntrinsics::_dsin: case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos: case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan: case vmIntrinsics::_dtan:
case vmIntrinsics::_dlog:
case vmIntrinsics::_dlog10: case vmIntrinsics::_dlog10:
case vmIntrinsics::_dpow: case vmIntrinsics::_dpow:
use_fpu = true; use_fpu = true;
@ -873,7 +872,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break; case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dlog: __ log (calc_input, calc_result, tmp1); break;
case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break; case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break;
case vmIntrinsics::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break; case vmIntrinsics::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
default: ShouldNotReachHere(); default: ShouldNotReachHere();
@ -884,7 +882,7 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
} }
} }
void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) { void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
LIRItem value(x->argument_at(0), this); LIRItem value(x->argument_at(0), this);
value.set_destroys_register(); value.set_destroys_register();
@ -900,13 +898,33 @@ void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) {
#ifndef _LP64 #ifndef _LP64
LIR_Opr tmp = FrameMap::fpu0_double_opr; LIR_Opr tmp = FrameMap::fpu0_double_opr;
result_reg = tmp; result_reg = tmp;
switch(x->id()) {
case vmIntrinsics::_dexp:
if (VM_Version::supports_sse2()) { if (VM_Version::supports_sse2()) {
__ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args()); __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
} else { } else {
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args()); __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
} }
break;
case vmIntrinsics::_dlog:
if (VM_Version::supports_sse2()) {
__ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
}
else {
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
}
break;
default: ShouldNotReachHere();
}
#else #else
switch (x->id()) {
case vmIntrinsics::_dexp:
__ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args()); __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
break;
case vmIntrinsics::_dlog:
__ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
break;
}
#endif #endif
__ move(result_reg, calc_result); __ move(result_reg, calc_result);
} }

View file

@ -786,7 +786,6 @@ void FpuStackAllocator::handle_op2(LIR_Op2* op2) {
break; break;
} }
case lir_log:
case lir_log10: { case lir_log10: {
// log and log10 need one temporary fpu stack slot, so // log and log10 need one temporary fpu stack slot, so
// there is one temporary registers stored in temp of the // there is one temporary registers stored in temp of the

View file

@ -132,10 +132,15 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
__ fabs(); __ fabs();
break; break;
case Interpreter::java_lang_math_log: case Interpreter::java_lang_math_log:
__ flog(); __ subptr(rsp, 2 * wordSize);
// Store to stack to convert 80bit precision back to 64bits __ fstp_d(Address(rsp, 0));
__ push_fTOS(); if (VM_Version::supports_sse2()) {
__ pop_fTOS(); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
}
else {
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dlog)));
}
__ addptr(rsp, 2 * wordSize);
break; break;
case Interpreter::java_lang_math_log10: case Interpreter::java_lang_math_log10:
__ flog10(); __ flog10();

View file

@ -253,6 +253,9 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
} else if (kind == Interpreter::java_lang_math_exp) { } else if (kind == Interpreter::java_lang_math_exp) {
__ movdbl(xmm0, Address(rsp, wordSize)); __ movdbl(xmm0, Address(rsp, wordSize));
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp()))); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
} else if (kind == Interpreter::java_lang_math_log) {
__ movdbl(xmm0, Address(rsp, wordSize));
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
} else { } else {
__ fld_d(Address(rsp, wordSize)); __ fld_d(Address(rsp, wordSize));
switch (kind) { switch (kind) {
@ -268,9 +271,6 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
case Interpreter::java_lang_math_abs: case Interpreter::java_lang_math_abs:
__ fabs(); __ fabs();
break; break;
case Interpreter::java_lang_math_log:
__ flog();
break;
case Interpreter::java_lang_math_log10: case Interpreter::java_lang_math_log10:
__ flog10(); __ flog10();
break; break;

View file

@ -56,6 +56,8 @@ class MacroAssembler: public Assembler {
#define VIRTUAL virtual #define VIRTUAL virtual
#endif #endif
#define COMMA ,
VIRTUAL void call_VM_leaf_base( VIRTUAL void call_VM_leaf_base(
address entry_point, // the entry point address entry_point, // the entry point
int number_of_arguments // the number of arguments to pop after the call int number_of_arguments // the number of arguments to pop after the call
@ -910,6 +912,11 @@ class MacroAssembler: public Assembler {
void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
Register rax, Register rcx, Register rdx, Register tmp); Register rax, Register rcx, Register rdx, Register tmp);
void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
Register rax, Register rcx, Register rdx, Register tmp1 LP64_ONLY(COMMA Register tmp2));
void increase_precision(); void increase_precision();
void restore_precision(); void restore_precision();

View file

@ -24,8 +24,19 @@
* *
*/ */
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
/******************************************************************************/ /******************************************************************************/
// ALGORITHM DESCRIPTION // ALGORITHM DESCRIPTION - EXP()
// --------------------- // ---------------------
// //
// Description: // Description:
@ -58,18 +69,6 @@
// //
/******************************************************************************/ /******************************************************************************/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#ifdef _LP64 #ifdef _LP64
ALIGNED_(16) juint _cv[] = ALIGNED_(16) juint _cv[] =
@ -409,6 +408,7 @@ void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
bind(B1_5); bind(B1_5);
addq(rsp, 24); addq(rsp, 24);
} }
#endif #endif
#ifndef _LP64 #ifndef _LP64
@ -675,3 +675,614 @@ void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
} }
#endif #endif
/******************************************************************************/
// ALGORITHM DESCRIPTION - LOG()
// ---------------------
//
// x=2^k * mx, mx in [1,2)
//
// Get B~1/mx based on the output of rcpss instruction (B0)
// B = int((B0*2^7+0.5))/2^7
//
// Reduced argument: r=B*mx-1.0 (computed accurately in high and low parts)
//
// Result: k*log(2) - log(B) + p(r) if |x-1| >= small value (2^-6) and
// p(r) is a degree 7 polynomial
// -log(B) read from data table (high, low parts)
// Result is formed from high and low parts
//
// Special cases:
// log(NaN) = quiet NaN, and raise invalid exception
// log(+INF) = that INF
// log(0) = -INF with divide-by-zero exception raised
// log(1) = +0
// log(x) = NaN with invalid exception raised if x < -0, including -INF
//
/******************************************************************************/
#ifdef _LP64
ALIGNED_(16) juint _L_tbl[] =
{
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
0x80000000UL
};
ALIGNED_(16) juint _log2[] =
{
0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL
};
ALIGNED_(16) juint _coeff[] =
{
0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
0x00000000UL, 0xbfe00000UL
};
//registers,
// input: xmm0
// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
// rax, rdx, rcx, r8, r11
void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp1, Register tmp2) {
Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
Label L_2TAG_PACKET_8_0_2;
Label L_2TAG_PACKET_12_0_2, L_2TAG_PACKET_13_0_2, B1_3, B1_5, start;
assert_different_registers(tmp1, tmp2, eax, ecx, edx);
jmp(start);
address L_tbl = (address)_L_tbl;
address log2 = (address)_log2;
address coeff = (address)_coeff;
bind(start);
subq(rsp, 24);
movsd(Address(rsp, 0), xmm0);
mov64(rax, 0x3ff0000000000000);
movdq(xmm2, rax);
mov64(rdx, 0x77f0000000000000);
movdq(xmm3, rdx);
movl(ecx, 32768);
movdl(xmm4, rcx);
mov64(tmp1, 0xffffe00000000000);
movdq(xmm5, tmp1);
movdqu(xmm1, xmm0);
pextrw(eax, xmm0, 3);
por(xmm0, xmm2);
movl(ecx, 16352);
psrlq(xmm0, 27);
lea(tmp2, ExternalAddress(L_tbl));
psrld(xmm0, 2);
rcpps(xmm0, xmm0);
psllq(xmm1, 12);
pshufd(xmm6, xmm5, 228);
psrlq(xmm1, 12);
subl(eax, 16);
cmpl(eax, 32736);
jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
bind(L_2TAG_PACKET_1_0_2);
paddd(xmm0, xmm4);
por(xmm1, xmm3);
movdl(edx, xmm0);
psllq(xmm0, 29);
pand(xmm5, xmm1);
pand(xmm0, xmm6);
subsd(xmm1, xmm5);
mulpd(xmm5, xmm0);
andl(eax, 32752);
subl(eax, ecx);
cvtsi2sdl(xmm7, eax);
mulsd(xmm1, xmm0);
movq(xmm6, ExternalAddress(log2)); // 0xfefa3800UL, 0x3fa62e42UL
movdqu(xmm3, ExternalAddress(coeff)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
subsd(xmm5, xmm2);
andl(edx, 16711680);
shrl(edx, 12);
movdqu(xmm0, Address(tmp2, edx));
movdqu(xmm4, ExternalAddress(16 + coeff)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
addsd(xmm1, xmm5);
movdqu(xmm2, ExternalAddress(32 + coeff)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
mulsd(xmm6, xmm7);
movddup(xmm5, xmm1);
mulsd(xmm7, ExternalAddress(8 + log2)); // 0x93c76730UL, 0x3ceef357UL
mulsd(xmm3, xmm1);
addsd(xmm0, xmm6);
mulpd(xmm4, xmm5);
mulpd(xmm5, xmm5);
movddup(xmm6, xmm0);
addsd(xmm0, xmm1);
addpd(xmm4, xmm2);
mulpd(xmm3, xmm5);
subsd(xmm6, xmm0);
mulsd(xmm4, xmm1);
pshufd(xmm2, xmm0, 238);
addsd(xmm1, xmm6);
mulsd(xmm5, xmm5);
addsd(xmm7, xmm2);
addpd(xmm4, xmm3);
addsd(xmm1, xmm7);
mulpd(xmm4, xmm5);
addsd(xmm1, xmm4);
pshufd(xmm5, xmm4, 238);
addsd(xmm1, xmm5);
addsd(xmm0, xmm1);
jmp(B1_5);
bind(L_2TAG_PACKET_0_0_2);
movq(xmm0, Address(rsp, 0));
movq(xmm1, Address(rsp, 0));
addl(eax, 16);
cmpl(eax, 32768);
jcc(Assembler::aboveEqual, L_2TAG_PACKET_2_0_2);
cmpl(eax, 16);
jcc(Assembler::below, L_2TAG_PACKET_3_0_2);
bind(L_2TAG_PACKET_4_0_2);
addsd(xmm0, xmm0);
jmp(B1_5);
bind(L_2TAG_PACKET_5_0_2);
jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
cmpl(edx, 0);
jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
jmp(L_2TAG_PACKET_6_0_2);
bind(L_2TAG_PACKET_3_0_2);
xorpd(xmm1, xmm1);
addsd(xmm1, xmm0);
movdl(edx, xmm1);
psrlq(xmm1, 32);
movdl(ecx, xmm1);
orl(edx, ecx);
cmpl(edx, 0);
jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
xorpd(xmm1, xmm1);
movl(eax, 18416);
pinsrw(xmm1, eax, 3);
mulsd(xmm0, xmm1);
movdqu(xmm1, xmm0);
pextrw(eax, xmm0, 3);
por(xmm0, xmm2);
psrlq(xmm0, 27);
movl(ecx, 18416);
psrld(xmm0, 2);
rcpps(xmm0, xmm0);
psllq(xmm1, 12);
pshufd(xmm6, xmm5, 228);
psrlq(xmm1, 12);
jmp(L_2TAG_PACKET_1_0_2);
bind(L_2TAG_PACKET_2_0_2);
movdl(edx, xmm1);
psrlq(xmm1, 32);
movdl(ecx, xmm1);
addl(ecx, ecx);
cmpl(ecx, -2097152);
jcc(Assembler::aboveEqual, L_2TAG_PACKET_5_0_2);
orl(edx, ecx);
cmpl(edx, 0);
jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
bind(L_2TAG_PACKET_6_0_2);
xorpd(xmm1, xmm1);
xorpd(xmm0, xmm0);
movl(eax, 32752);
pinsrw(xmm1, eax, 3);
mulsd(xmm0, xmm1);
movl(Address(rsp, 16), 3);
jmp(L_2TAG_PACKET_8_0_2);
bind(L_2TAG_PACKET_7_0_2);
xorpd(xmm1, xmm1);
xorpd(xmm0, xmm0);
movl(eax, 49136);
pinsrw(xmm0, eax, 3);
divsd(xmm0, xmm1);
movl(Address(rsp, 16), 2);
bind(L_2TAG_PACKET_8_0_2);
movq(Address(rsp, 8), xmm0);
bind(B1_3);
movq(xmm0, Address(rsp, 8));
bind(B1_5);
addq(rsp, 24);
}
#endif
#ifndef _LP64
ALIGNED_(16) juint _static_const_table_log[] =
{
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
0x80000000UL, 0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL,
0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
0x00000000UL, 0xbfe00000UL, 0x00000000UL, 0xffffe000UL, 0x00000000UL,
0xffffe000UL
};
//registers,
// input: xmm0
// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
// rax, rdx, rcx, rbx (tmp)
void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp) {
Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
Label L_2TAG_PACKET_8_0_2, L_2TAG_PACKET_9_0_2;
Label L_2TAG_PACKET_10_0_2, start;
assert_different_registers(tmp, eax, ecx, edx);
jmp(start);
address static_const_table = (address)_static_const_table_log;
bind(start);
subl(rsp, 104);
movl(Address(rsp, 40), tmp);
lea(tmp, ExternalAddress(static_const_table));
xorpd(xmm2, xmm2);
movl(eax, 16368);
pinsrw(xmm2, eax, 3);
xorpd(xmm3, xmm3);
movl(edx, 30704);
pinsrw(xmm3, edx, 3);
movsd(xmm0, Address(rsp, 112));
movapd(xmm1, xmm0);
movl(ecx, 32768);
movdl(xmm4, ecx);
movsd(xmm5, Address(tmp, 2128)); // 0x00000000UL, 0xffffe000UL
pextrw(eax, xmm0, 3);
por(xmm0, xmm2);
psllq(xmm0, 5);
movl(ecx, 16352);
psrlq(xmm0, 34);
rcpss(xmm0, xmm0);
psllq(xmm1, 12);
pshufd(xmm6, xmm5, 228);
psrlq(xmm1, 12);
subl(eax, 16);
cmpl(eax, 32736);
jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
bind(L_2TAG_PACKET_1_0_2);
paddd(xmm0, xmm4);
por(xmm1, xmm3);
movdl(edx, xmm0);
psllq(xmm0, 29);
pand(xmm5, xmm1);
pand(xmm0, xmm6);
subsd(xmm1, xmm5);
mulpd(xmm5, xmm0);
andl(eax, 32752);
subl(eax, ecx);
cvtsi2sdl(xmm7, eax);
mulsd(xmm1, xmm0);
movsd(xmm6, Address(tmp, 2064)); // 0xfefa3800UL, 0x3fa62e42UL
movdqu(xmm3, Address(tmp, 2080)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
subsd(xmm5, xmm2);
andl(edx, 16711680);
shrl(edx, 12);
movdqu(xmm0, Address(tmp, edx));
movdqu(xmm4, Address(tmp, 2096)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
addsd(xmm1, xmm5);
movdqu(xmm2, Address(tmp, 2112)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
mulsd(xmm6, xmm7);
pshufd(xmm5, xmm1, 68);
mulsd(xmm7, Address(tmp, 2072)); // 0x93c76730UL, 0x3ceef357UL, 0x92492492UL, 0x3fc24924UL
mulsd(xmm3, xmm1);
addsd(xmm0, xmm6);
mulpd(xmm4, xmm5);
mulpd(xmm5, xmm5);
pshufd(xmm6, xmm0, 228);
addsd(xmm0, xmm1);
addpd(xmm4, xmm2);
mulpd(xmm3, xmm5);
subsd(xmm6, xmm0);
mulsd(xmm4, xmm1);
pshufd(xmm2, xmm0, 238);
addsd(xmm1, xmm6);
mulsd(xmm5, xmm5);
addsd(xmm7, xmm2);
addpd(xmm4, xmm3);
addsd(xmm1, xmm7);
mulpd(xmm4, xmm5);
addsd(xmm1, xmm4);
pshufd(xmm5, xmm4, 238);
addsd(xmm1, xmm5);
addsd(xmm0, xmm1);
jmp(L_2TAG_PACKET_2_0_2);
bind(L_2TAG_PACKET_0_0_2);
movsd(xmm0, Address(rsp, 112));
movdqu(xmm1, xmm0);
addl(eax, 16);
cmpl(eax, 32768);
jcc(Assembler::aboveEqual, L_2TAG_PACKET_3_0_2);
cmpl(eax, 16);
jcc(Assembler::below, L_2TAG_PACKET_4_0_2);
bind(L_2TAG_PACKET_5_0_2);
addsd(xmm0, xmm0);
jmp(L_2TAG_PACKET_2_0_2);
bind(L_2TAG_PACKET_6_0_2);
jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
cmpl(edx, 0);
jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
jmp(L_2TAG_PACKET_7_0_2);
bind(L_2TAG_PACKET_3_0_2);
movdl(edx, xmm1);
psrlq(xmm1, 32);
movdl(ecx, xmm1);
addl(ecx, ecx);
cmpl(ecx, -2097152);
jcc(Assembler::aboveEqual, L_2TAG_PACKET_6_0_2);
orl(edx, ecx);
cmpl(edx, 0);
jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
bind(L_2TAG_PACKET_7_0_2);
xorpd(xmm1, xmm1);
xorpd(xmm0, xmm0);
movl(eax, 32752);
pinsrw(xmm1, eax, 3);
movl(edx, 3);
mulsd(xmm0, xmm1);
bind(L_2TAG_PACKET_9_0_2);
movsd(Address(rsp, 0), xmm0);
movsd(xmm0, Address(rsp, 112));
fld_d(Address(rsp, 0));
jmp(L_2TAG_PACKET_10_0_2);
bind(L_2TAG_PACKET_8_0_2);
xorpd(xmm1, xmm1);
xorpd(xmm0, xmm0);
movl(eax, 49136);
pinsrw(xmm0, eax, 3);
divsd(xmm0, xmm1);
movl(edx, 2);
jmp(L_2TAG_PACKET_9_0_2);
bind(L_2TAG_PACKET_4_0_2);
movdl(edx, xmm1);
psrlq(xmm1, 32);
movdl(ecx, xmm1);
orl(edx, ecx);
cmpl(edx, 0);
jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
xorpd(xmm1, xmm1);
movl(eax, 18416);
pinsrw(xmm1, eax, 3);
mulsd(xmm0, xmm1);
movapd(xmm1, xmm0);
pextrw(eax, xmm0, 3);
por(xmm0, xmm2);
psllq(xmm0, 5);
movl(ecx, 18416);
psrlq(xmm0, 34);
rcpss(xmm0, xmm0);
psllq(xmm1, 12);
pshufd(xmm6, xmm5, 228);
psrlq(xmm1, 12);
jmp(L_2TAG_PACKET_1_0_2);
bind(L_2TAG_PACKET_2_0_2);
movsd(Address(rsp, 24), xmm0);
fld_d(Address(rsp, 24));
bind(L_2TAG_PACKET_10_0_2);
movl(tmp, Address(rsp, 40));
}
#endif

View file

@ -2094,14 +2094,6 @@ class StubGenerator: public StubCodeGenerator {
} }
void generate_math_stubs() { void generate_math_stubs() {
{
StubCodeMark mark(this, "StubRoutines", "log");
StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
__ fld_d(Address(rsp, 4));
__ flog();
__ ret(0);
}
{ {
StubCodeMark mark(this, "StubRoutines", "log10"); StubCodeMark mark(this, "StubRoutines", "log10");
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc(); StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
@ -3065,6 +3057,32 @@ class StubGenerator: public StubCodeGenerator {
} }
address generate_libmLog() {
address start = __ pc();
const XMMRegister x0 = xmm0;
const XMMRegister x1 = xmm1;
const XMMRegister x2 = xmm2;
const XMMRegister x3 = xmm3;
const XMMRegister x4 = xmm4;
const XMMRegister x5 = xmm5;
const XMMRegister x6 = xmm6;
const XMMRegister x7 = xmm7;
const Register tmp = rbx;
BLOCK_COMMENT("Entry:");
__ enter(); // required for proper stackwalking of RuntimeStub frame
__ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
__ leave(); // required for proper stackwalking of RuntimeStub frame
__ ret(0);
return start;
}
// Safefetch stubs. // Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry, void generate_safefetch(const char* name, int size, address* entry,
@ -3288,6 +3306,7 @@ class StubGenerator: public StubCodeGenerator {
} }
if (VM_Version::supports_sse2()) { if (VM_Version::supports_sse2()) {
StubRoutines::_dexp = generate_libmExp(); StubRoutines::_dexp = generate_libmExp();
StubRoutines::_dlog = generate_libmLog();
} }
} }

View file

@ -2973,19 +2973,6 @@ class StubGenerator: public StubCodeGenerator {
} }
void generate_math_stubs() { void generate_math_stubs() {
{
StubCodeMark mark(this, "StubRoutines", "log");
StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
__ subq(rsp, 8);
__ movdbl(Address(rsp, 0), xmm0);
__ fld_d(Address(rsp, 0));
__ flog();
__ fstp_d(Address(rsp, 0));
__ movdbl(xmm0, Address(rsp, 0));
__ addq(rsp, 8);
__ ret(0);
}
{ {
StubCodeMark mark(this, "StubRoutines", "log10"); StubCodeMark mark(this, "StubRoutines", "log10");
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc(); StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
@ -4187,15 +4174,58 @@ class StubGenerator: public StubCodeGenerator {
#ifdef _WIN64 #ifdef _WIN64
// save the xmm registers which must be preserved 6-7 // save the xmm registers which must be preserved 6-7
__ movdqu(xmm_save(6), as_XMMRegister(6)); __ subptr(rsp, 4 * wordSize);
__ movdqu(xmm_save(7), as_XMMRegister(7)); __ movdqu(Address(rsp, 0), xmm6);
__ movdqu(Address(rsp, 2 * wordSize), xmm7);
#endif #endif
__ 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);
#ifdef _WIN64 #ifdef _WIN64
// restore xmm regs belonging to calling function // restore xmm regs belonging to calling function
__ movdqu(as_XMMRegister(6), xmm_save(6)); __ movdqu(xmm6, Address(rsp, 0));
__ movdqu(as_XMMRegister(7), xmm_save(7)); __ movdqu(xmm7, Address(rsp, 2 * wordSize));
__ addptr(rsp, 4 * wordSize);
#endif
__ leave(); // required for proper stackwalking of RuntimeStub frame
__ ret(0);
return start;
}
address generate_libmLog() {
address start = __ pc();
const XMMRegister x0 = xmm0;
const XMMRegister x1 = xmm1;
const XMMRegister x2 = xmm2;
const XMMRegister x3 = xmm3;
const XMMRegister x4 = xmm4;
const XMMRegister x5 = xmm5;
const XMMRegister x6 = xmm6;
const XMMRegister x7 = xmm7;
const Register tmp1 = r11;
const Register tmp2 = r8;
BLOCK_COMMENT("Entry:");
__ enter(); // required for proper stackwalking of RuntimeStub frame
#ifdef _WIN64
// save the xmm registers which must be preserved 6-7
__ subptr(rsp, 4 * wordSize);
__ movdqu(Address(rsp, 0), xmm6);
__ movdqu(Address(rsp, 2 * wordSize), xmm7);
#endif
__ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2);
#ifdef _WIN64
// restore xmm regs belonging to calling function
__ movdqu(xmm6, Address(rsp, 0));
__ movdqu(xmm7, Address(rsp, 2 * wordSize));
__ addptr(rsp, 4 * wordSize);
#endif #endif
__ leave(); // required for proper stackwalking of RuntimeStub frame __ leave(); // required for proper stackwalking of RuntimeStub frame
@ -4392,7 +4422,10 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table; StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table;
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul); StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul);
} }
if (VM_Version::supports_sse2()) {
StubRoutines::_dexp = generate_libmExp(); StubRoutines::_dexp = generate_libmExp();
StubRoutines::_dlog = generate_libmLog();
}
} }
void generate_all() { void generate_all() {

View file

@ -1707,6 +1707,10 @@ const bool Matcher::match_rule_supported(int opcode) {
if (!VM_Version::supports_cx8()) if (!VM_Version::supports_cx8())
ret_value = false; ret_value = false;
break; break;
case Op_CMoveVD:
if (UseAVX < 1 || UseAVX > 2)
ret_value = false;
break;
} }
return ret_value; // Per default match rules are supported. return ret_value; // Per default match rules are supported.
@ -2089,6 +2093,29 @@ operand vecZ() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
// Comparison Code for FP conditional move
operand cmpOp_vcmppd() %{
match(Bool);
predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
n->as_Bool()->_test._test != BoolTest::no_overflow);
format %{ "" %}
interface(COND_INTER) %{
equal (0x0, "eq");
less (0x1, "lt");
less_equal (0x2, "le");
not_equal (0xC, "ne");
greater_equal(0xD, "ge");
greater (0xE, "gt");
//TODO cannot compile (adlc breaks) without two next lines with error:
// x86_64.ad(13987) Syntax Error: :In operand cmpOp_vcmppd: Do not support this encode constant: ' %{
// equal' for overflow.
overflow (0x20, "o"); // not really supported by the instruction
no_overflow (0x21, "no"); // not really supported by the instruction
%}
%}
// INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit) // INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit)
// ============================================================================ // ============================================================================
@ -7393,6 +7420,22 @@ instruct vmul8D_mem(vecZ dst, vecZ src, memory mem) %{
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
instruct vcmov4D_reg(vecY dst, vecY src1, vecY src2, immI8 cop, cmpOp_vcmppd copnd) %{
predicate(UseAVX > 0 && UseAVX < 3 && n->as_Vector()->length() == 4);
match(Set dst (CMoveVD (Binary copnd cop) (Binary src1 src2)));
effect(TEMP dst, USE src1, USE src2);
format %{ "cmppd.$copnd $dst, $src1, $src2 ! vcmovevd, cond=$cop\n\t"
"vpblendd $dst,$src1,$src2,$dst ! vcmovevd\n\t"
%}
ins_encode %{
int vector_len = 1;
int cond = (Assembler::Condition)($copnd$$cmpcode);
__ cmppd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, cond, vector_len);
__ vpblendd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
%}
// --------------------------------- DIV -------------------------------------- // --------------------------------- DIV --------------------------------------
// Floats vector div // Floats vector div

View file

@ -9950,41 +9950,6 @@ instruct log10D_reg(regD dst, regD src, eFlagsReg cr) %{
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
instruct logDPR_reg(regDPR1 dst, regDPR1 src) %{
predicate (UseSSE<=1);
// The source Double operand on FPU stack
match(Set dst (LogD src));
// fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
// fxch ; swap ST(0) with ST(1)
// fyl2x ; compute log_e(2) * log_2(x)
format %{ "FLDLN2 \t\t\t#Log_e\n\t"
"FXCH \n\t"
"FYL2X \t\t\t# Q=Log_e*Log_2(x)"
%}
ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
Opcode(0xD9), Opcode(0xC9), // fxch
Opcode(0xD9), Opcode(0xF1)); // fyl2x
ins_pipe( pipe_slow );
%}
instruct logD_reg(regD dst, regD src, eFlagsReg cr) %{
predicate (UseSSE>=2);
effect(KILL cr);
// The source and result Double operands in XMM registers
match(Set dst (LogD src));
// fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
// fyl2x ; compute log_e(2) * log_2(x)
format %{ "FLDLN2 \t\t\t#Log_e\n\t"
"FYL2X \t\t\t# Q=Log_e*Log_2(x)"
%}
ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
Push_SrcD(src),
Opcode(0xD9), Opcode(0xF1), // fyl2x
Push_ResultD(dst));
ins_pipe( pipe_slow );
%}
//-------------Float Instructions------------------------------- //-------------Float Instructions-------------------------------
// Float Math // Float Math

View file

@ -9870,21 +9870,6 @@ instruct log10D_reg(regD dst) %{
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
instruct logD_reg(regD dst) %{
// The source and result Double operands in XMM registers
match(Set dst (LogD dst));
// fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
// fyl2x ; compute log_e(2) * log_2(x)
format %{ "fldln2\t\t\t#Log_e\n\t"
"fyl2x\t\t\t# Q=Log_e*Log_2(x)\n\t"
%}
ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
Push_SrcXD(dst),
Opcode(0xD9), Opcode(0xF1), // fyl2x
Push_ResultXD(dst));
ins_pipe( pipe_slow );
%}
instruct powD_reg(regD dst, regD src0, regD src1, rax_RegI rax, rdx_RegI rdx, rcx_RegI rcx, rFlagsReg cr) %{ instruct powD_reg(regD dst, regD src0, regD src1, rax_RegI rax, rdx_RegI rdx, rcx_RegI rcx, rFlagsReg cr) %{
match(Set dst (PowD src0 src1)); // Raise src0 to the src1'th power match(Set dst (PowD src0 src1)); // Raise src0 to the src1'th power
effect(KILL rax, KILL rdx, KILL rcx, KILL cr); effect(KILL rax, KILL rdx, KILL rcx, KILL cr);

View file

@ -60,7 +60,7 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) { address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
ShouldNotReachHere(); // Only needed for COMPILER2. ShouldNotReachHere(); // Only needed for COMPILER2.
return NULL; return NULL;
} }

View file

@ -59,11 +59,6 @@ void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src,
ShouldNotCallThis(); ShouldNotCallThis();
} }
void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
CodeBuffer* dst) {
ShouldNotCallThis();
}
void metadata_Relocation::pd_fix_value(address x) { void metadata_Relocation::pd_fix_value(address x) {
ShouldNotCallThis(); ShouldNotCallThis();
} }

View file

@ -37,4 +37,5 @@ void VM_Version::initialize() {
warning("Unaligned memory access is not available on this CPU"); warning("Unaligned memory access is not available on this CPU");
FLAG_SET_DEFAULT(UseUnalignedAccesses, false); FLAG_SET_DEFAULT(UseUnalignedAccesses, false);
} }
FLAG_SET_DEFAULT(AllocatePrefetchDistance, 0);
} }

View file

@ -4006,7 +4006,6 @@ int MatchRule::is_expensive() const {
strcmp(opType,"DivD")==0 || strcmp(opType,"DivD")==0 ||
strcmp(opType,"DivF")==0 || strcmp(opType,"DivF")==0 ||
strcmp(opType,"DivI")==0 || strcmp(opType,"DivI")==0 ||
strcmp(opType,"LogD")==0 ||
strcmp(opType,"Log10D")==0 || strcmp(opType,"Log10D")==0 ||
strcmp(opType,"ModD")==0 || strcmp(opType,"ModD")==0 ||
strcmp(opType,"ModF")==0 || strcmp(opType,"ModF")==0 ||
@ -4141,6 +4140,7 @@ bool MatchRule::is_vector() const {
"AddVB","AddVS","AddVI","AddVL","AddVF","AddVD", "AddVB","AddVS","AddVI","AddVL","AddVF","AddVD",
"SubVB","SubVS","SubVI","SubVL","SubVF","SubVD", "SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",
"MulVS","MulVI","MulVL","MulVF","MulVD", "MulVS","MulVI","MulVL","MulVF","MulVD",
"CMoveVD",
"DivVF","DivVD", "DivVF","DivVD",
"AbsVF","AbsVD", "AbsVF","AbsVD",
"NegVF","NegVD", "NegVF","NegVD",

View file

@ -34,6 +34,7 @@
#include "c1/c1_ValueStack.hpp" #include "c1/c1_ValueStack.hpp"
#include "code/debugInfoRec.hpp" #include "code/debugInfoRec.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "compiler/compilerDirectives.hpp"
#include "runtime/sharedRuntime.hpp" #include "runtime/sharedRuntime.hpp"
typedef enum { typedef enum {
@ -418,9 +419,9 @@ void Compilation::install_code(int frame_size) {
exception_handler_table(), exception_handler_table(),
implicit_exception_table(), implicit_exception_table(),
compiler(), compiler(),
_env->comp_level(),
has_unsafe_access(), has_unsafe_access(),
SharedRuntime::is_wide_vector(max_vector_size()) SharedRuntime::is_wide_vector(max_vector_size()),
directive()
); );
} }
@ -445,7 +446,7 @@ void Compilation::compile_method() {
dependency_recorder()->assert_evol_method(method()); dependency_recorder()->assert_evol_method(method());
} }
if (method()->break_at_execute()) { if (directive()->BreakAtCompileOption) {
BREAKPOINT; BREAKPOINT;
} }
@ -534,9 +535,10 @@ void Compilation::generate_exception_handler_table() {
Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method, Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
int osr_bci, BufferBlob* buffer_blob) int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive)
: _compiler(compiler) : _compiler(compiler)
, _env(env) , _env(env)
, _directive(directive)
, _log(env->log()) , _log(env->log())
, _method(method) , _method(method)
, _osr_bci(osr_bci) , _osr_bci(osr_bci)
@ -587,7 +589,6 @@ Compilation::~Compilation() {
_env->set_compiler_data(NULL); _env->set_compiler_data(NULL);
} }
void Compilation::add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers) { void Compilation::add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers) {
#ifndef PRODUCT #ifndef PRODUCT
if (PrintExceptionHandlers && Verbose) { if (PrintExceptionHandlers && Verbose) {

View file

@ -67,6 +67,7 @@ class Compilation: public StackObj {
int _next_id; int _next_id;
int _next_block_id; int _next_block_id;
AbstractCompiler* _compiler; AbstractCompiler* _compiler;
DirectiveSet* _directive;
ciEnv* _env; ciEnv* _env;
CompileLog* _log; CompileLog* _log;
ciMethod* _method; ciMethod* _method;
@ -118,7 +119,7 @@ class Compilation: public StackObj {
public: public:
// creation // creation
Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method, Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
int osr_bci, BufferBlob* buffer_blob); int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive);
~Compilation(); ~Compilation();
@ -128,6 +129,7 @@ class Compilation: public StackObj {
// accessors // accessors
ciEnv* env() const { return _env; } ciEnv* env() const { return _env; }
DirectiveSet* directive() const { return _directive; }
CompileLog* log() const { return _log; } CompileLog* log() const { return _log; }
AbstractCompiler* compiler() const { return _compiler; } AbstractCompiler* compiler() const { return _compiler; }
bool has_exception_handlers() const { return _has_exception_handlers; } bool has_exception_handlers() const { return _has_exception_handlers; }

View file

@ -238,7 +238,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
return true; return true;
} }
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) { void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob(); BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
assert(buffer_blob != NULL, "Must exist"); assert(buffer_blob != NULL, "Must exist");
// invoke compilation // invoke compilation
@ -247,7 +247,7 @@ void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
// of Compilation to occur before we release the any // of Compilation to occur before we release the any
// competing compiler thread // competing compiler thread
ResourceMark rm; ResourceMark rm;
Compilation c(this, env, method, entry_bci, buffer_blob); Compilation c(this, env, method, entry_bci, buffer_blob, directive);
} }
} }

View file

@ -26,6 +26,7 @@
#define SHARE_VM_C1_C1_COMPILER_HPP #define SHARE_VM_C1_C1_COMPILER_HPP
#include "compiler/abstractCompiler.hpp" #include "compiler/abstractCompiler.hpp"
#include "compiler/compilerDirectives.hpp"
// There is one instance of the Compiler per CompilerThread. // There is one instance of the Compiler per CompilerThread.
@ -50,7 +51,7 @@ class Compiler: public AbstractCompiler {
virtual void initialize(); virtual void initialize();
// Compilation entry point for methods // Compilation entry point for methods
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
// Print compilation timers and statistics // Print compilation timers and statistics
virtual void print_timers(); virtual void print_timers();

View file

@ -3365,7 +3365,7 @@ const char* GraphBuilder::check_can_parse(ciMethod* callee) const {
// negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg // negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg
const char* GraphBuilder::should_not_inline(ciMethod* callee) const { const char* GraphBuilder::should_not_inline(ciMethod* callee) const {
if ( callee->should_not_inline()) return "disallowed by CompileCommand"; if ( compilation()->directive()->should_not_inline(callee)) return "disallowed by CompileCommand";
if ( callee->dont_inline()) return "don't inline by annotation"; if ( callee->dont_inline()) return "don't inline by annotation";
return NULL; return NULL;
} }
@ -3494,8 +3494,7 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
{ {
VM_ENTRY_MARK; VM_ENTRY_MARK;
methodHandle mh(THREAD, callee->get_Method()); methodHandle mh(THREAD, callee->get_Method());
methodHandle ct(THREAD, method()->get_Method()); is_available = _compilation->compiler()->is_intrinsic_available(mh, _compilation->directive());
is_available = _compilation->compiler()->is_intrinsic_available(mh, ct);
} }
if (!is_available) { if (!is_available) {
@ -3690,13 +3689,14 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode
} }
// now perform tests that are based on flag settings // now perform tests that are based on flag settings
if (callee->force_inline() || callee->should_inline()) { bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
if (callee->force_inline() || inlinee_by_directive) {
if (inline_level() > MaxForceInlineLevel ) INLINE_BAILOUT("MaxForceInlineLevel"); if (inline_level() > MaxForceInlineLevel ) INLINE_BAILOUT("MaxForceInlineLevel");
if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");
const char* msg = ""; const char* msg = "";
if (callee->force_inline()) msg = "force inline by annotation"; if (callee->force_inline()) msg = "force inline by annotation";
if (callee->should_inline()) msg = "force inline by CompileCommand"; if (inlinee_by_directive) msg = "force inline by CompileCommand";
print_inlining(callee, msg); print_inlining(callee, msg);
} else { } else {
// use heuristic controls on inlining // use heuristic controls on inlining
@ -4207,7 +4207,8 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes
event.commit(); event.commit();
} }
#endif // INCLUDE_TRACE #endif // INCLUDE_TRACE
if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
if (!compilation()->directive()->PrintInliningOption) {
return; return;
} }
CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg); CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg);

View file

@ -731,7 +731,6 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
case lir_tan: case lir_tan:
case lir_sin: case lir_sin:
case lir_cos: case lir_cos:
case lir_log:
case lir_log10: { case lir_log10: {
assert(op->as_Op2() != NULL, "must be"); assert(op->as_Op2() != NULL, "must be");
LIR_Op2* op2 = (LIR_Op2*)op; LIR_Op2* op2 = (LIR_Op2*)op;
@ -1769,7 +1768,6 @@ const char * LIR_Op::name() const {
case lir_sin: s = "sin"; break; case lir_sin: s = "sin"; break;
case lir_cos: s = "cos"; break; case lir_cos: s = "cos"; break;
case lir_tan: s = "tan"; break; case lir_tan: s = "tan"; break;
case lir_log: s = "log"; break;
case lir_log10: s = "log10"; break; case lir_log10: s = "log10"; break;
case lir_pow: s = "pow"; break; case lir_pow: s = "pow"; break;
case lir_logic_and: s = "logic_and"; break; case lir_logic_and: s = "logic_and"; break;

View file

@ -959,7 +959,6 @@ enum LIR_Code {
, lir_sin , lir_sin
, lir_cos , lir_cos
, lir_tan , lir_tan
, lir_log
, lir_log10 , lir_log10
, lir_pow , lir_pow
, lir_logic_and , lir_logic_and
@ -2193,7 +2192,6 @@ class LIR_List: public CompilationResourceObj {
void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_abs , from, tmp, to)); } void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_abs , from, tmp, to)); }
void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_sqrt, from, tmp, to)); } void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_sqrt, from, tmp, to)); }
void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log, from, LIR_OprFact::illegalOpr, to, tmp)); }
void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); } void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); }
void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); } void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); }
void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); } void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); }

View file

@ -738,7 +738,6 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) {
case lir_sin: case lir_sin:
case lir_tan: case lir_tan:
case lir_cos: case lir_cos:
case lir_log:
case lir_log10: case lir_log10:
case lir_pow: case lir_pow:
intrinsic_op(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op); intrinsic_op(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op);

View file

@ -153,8 +153,13 @@ class PhiResolver: public CompilationResourceObj {
// only the classes below belong in the same file // only the classes below belong in the same file
class LIRGenerator: public InstructionVisitor, public BlockClosure { class LIRGenerator: public InstructionVisitor, public BlockClosure {
// LIRGenerator should never get instatiated on the heap.
private: private:
void* operator new(size_t size) throw();
void* operator new[](size_t size) throw();
void operator delete(void* p);
void operator delete[](void* p);
Compilation* _compilation; Compilation* _compilation;
ciMethod* _method; // method that we are compiling ciMethod* _method; // method that we are compiling
PhiResolverState _resolver_state; PhiResolverState _resolver_state;
@ -244,7 +249,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
void do_getClass(Intrinsic* x); void do_getClass(Intrinsic* x);
void do_currentThread(Intrinsic* x); void do_currentThread(Intrinsic* x);
void do_MathIntrinsic(Intrinsic* x); void do_MathIntrinsic(Intrinsic* x);
void do_ExpIntrinsic(Intrinsic* x); void do_LibmIntrinsic(Intrinsic* x);
void do_ArrayCopy(Intrinsic* x); void do_ArrayCopy(Intrinsic* x);
void do_CompareAndSwap(Intrinsic* x, ValueType* type); void do_CompareAndSwap(Intrinsic* x, ValueType* type);
void do_NIOCheckIndex(Intrinsic* x); void do_NIOCheckIndex(Intrinsic* x);

View file

@ -6586,7 +6586,6 @@ void LinearScanStatistic::collect(LinearScan* allocator) {
case lir_cos: case lir_cos:
case lir_abs: case lir_abs:
case lir_log10: case lir_log10:
case lir_log:
case lir_pow: case lir_pow:
case lir_logic_and: case lir_logic_and:
case lir_logic_or: case lir_logic_or:

View file

@ -45,8 +45,14 @@ private:
define_stack(IntegerStack, intArray) define_stack(IntegerStack, intArray)
define_array(IntegerMap, IntegerStack*) define_array(IntegerMap, IntegerStack*)
class Verification : public _ValueObj /*VALUE_OBJ_CLASS_SPEC*/, public BlockClosure { class Verification : public BlockClosure {
// RangeCheckEliminator::Verification should never get instatiated on the heap.
private: private:
void* operator new(size_t size) throw();
void* operator new[](size_t size) throw();
void operator delete(void* p);
void operator delete[](void* p);
IR *_ir; IR *_ir;
boolArray _used; boolArray _used;
BlockBeginList _current; BlockBeginList _current;

View file

@ -318,6 +318,7 @@ const char* Runtime1::name_for_address(address entry) {
#endif #endif
FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32()); FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32());
FUNCTION_CASE(entry, StubRoutines::dexp()); FUNCTION_CASE(entry, StubRoutines::dexp());
FUNCTION_CASE(entry, StubRoutines::dlog());
#undef FUNCTION_CASE #undef FUNCTION_CASE

View file

@ -38,7 +38,8 @@
#include "code/scopeDesc.hpp" #include "code/scopeDesc.hpp"
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp" #include "compiler/compilerDirectives.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp" #include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
@ -956,9 +957,9 @@ void ciEnv::register_method(ciMethod* target,
ExceptionHandlerTable* handler_table, ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* inc_table, ImplicitExceptionTable* inc_table,
AbstractCompiler* compiler, AbstractCompiler* compiler,
int comp_level,
bool has_unsafe_access, bool has_unsafe_access,
bool has_wide_vectors, bool has_wide_vectors,
DirectiveSet* directives,
RTMState rtm_state) { RTMState rtm_state) {
VM_ENTRY_MARK; VM_ENTRY_MARK;
nmethod* nm = NULL; nmethod* nm = NULL;
@ -1034,11 +1035,20 @@ void ciEnv::register_method(ciMethod* target,
debug_info(), dependencies(), code_buffer, debug_info(), dependencies(), code_buffer,
frame_words, oop_map_set, frame_words, oop_map_set,
handler_table, inc_table, handler_table, inc_table,
compiler, comp_level); compiler, task()->comp_level());
// Free codeBlobs // Free codeBlobs
code_buffer->free_blob(); code_buffer->free_blob();
if (nm != NULL) { if (nm != NULL) {
bool printnmethods = directives->PrintAssemblyOption || directives->PrintNMethodsOption;
if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
nm->print_nmethod(printnmethods);
}
if (directives->PrintAssemblyOption) {
Disassembler::decode(nm);
}
nm->set_has_unsafe_access(has_unsafe_access); nm->set_has_unsafe_access(has_unsafe_access);
nm->set_has_wide_vectors(has_wide_vectors); nm->set_has_wide_vectors(has_wide_vectors);
#if INCLUDE_RTM_OPT #if INCLUDE_RTM_OPT
@ -1069,7 +1079,7 @@ void ciEnv::register_method(ciMethod* target,
char *method_name = method->name_and_sig_as_C_string(); char *method_name = method->name_and_sig_as_C_string();
ttyLocker ttyl; ttyLocker ttyl;
tty->print_cr("Installing method (%d) %s ", tty->print_cr("Installing method (%d) %s ",
comp_level, task()->comp_level(),
method_name); method_name);
} }
// Allow the code to be executed // Allow the code to be executed
@ -1080,7 +1090,7 @@ void ciEnv::register_method(ciMethod* target,
char *method_name = method->name_and_sig_as_C_string(); char *method_name = method->name_and_sig_as_C_string();
ttyLocker ttyl; ttyLocker ttyl;
tty->print_cr("Installing osr method (%d) %s @ %d", tty->print_cr("Installing osr method (%d) %s @ %d",
comp_level, task()->comp_level(),
method_name, method_name,
entry_bci); entry_bci);
} }

View file

@ -32,9 +32,11 @@
#include "code/dependencies.hpp" #include "code/dependencies.hpp"
#include "code/exceptionHandlerTable.hpp" #include "code/exceptionHandlerTable.hpp"
#include "compiler/oopMap.hpp" #include "compiler/oopMap.hpp"
#include "compiler/compilerDirectives.hpp"
#include "runtime/thread.hpp" #include "runtime/thread.hpp"
class CompileTask; class CompileTask;
class DirectiveSet;
// ciEnv // ciEnv
// //
@ -352,6 +354,7 @@ public:
// The compiler task which has created this env. // The compiler task which has created this env.
// May be useful to find out compile_id, comp_level, etc. // May be useful to find out compile_id, comp_level, etc.
CompileTask* task() { return _task; } CompileTask* task() { return _task; }
// Handy forwards to the task: // Handy forwards to the task:
int comp_level(); // task()->comp_level() int comp_level(); // task()->comp_level()
uint compile_id(); // task()->compile_id() uint compile_id(); // task()->compile_id()
@ -367,9 +370,9 @@ public:
ExceptionHandlerTable* handler_table, ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* inc_table, ImplicitExceptionTable* inc_table,
AbstractCompiler* compiler, AbstractCompiler* compiler,
int comp_level,
bool has_unsafe_access, bool has_unsafe_access,
bool has_wide_vectors, bool has_wide_vectors,
DirectiveSet* directives,
RTMState rtm_state = NoRTM); RTMState rtm_state = NoRTM);

View file

@ -190,6 +190,14 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
// so there is no hacking of finals going on with them. // so there is no hacking of finals going on with them.
if (holder->is_anonymous()) if (holder->is_anonymous())
return true; return true;
// Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
// more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater() ||
holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater() ||
holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl()) {
return true;
}
return TrustFinalNonStaticFields; return TrustFinalNonStaticFields;
} }

View file

@ -35,7 +35,6 @@
#include "ci/ciUtilities.hpp" #include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "compiler/abstractCompiler.hpp" #include "compiler/abstractCompiler.hpp"
#include "compiler/compilerOracle.hpp"
#include "compiler/methodLiveness.hpp" #include "compiler/methodLiveness.hpp"
#include "interpreter/interpreter.hpp" #include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
@ -1043,51 +1042,6 @@ MethodCounters* ciMethod::ensure_method_counters() {
return method_counters; return method_counters;
} }
// ------------------------------------------------------------------
// ciMethod::should_inline
//
// Should this method be inlined during compilation?
bool ciMethod::should_inline() {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
return CompilerOracle::should_inline(mh);
}
// ------------------------------------------------------------------
// ciMethod::should_not_inline
//
// Should this method be disallowed from inlining during compilation?
bool ciMethod::should_not_inline() {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
return CompilerOracle::should_not_inline(mh);
}
// ------------------------------------------------------------------
// ciMethod::should_print_assembly
//
// Should the compiler print the generated code for this method?
bool ciMethod::should_print_assembly() {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
return CompilerOracle::should_print(mh);
}
// ------------------------------------------------------------------
// ciMethod::break_at_execute
//
// Should the compiler insert a breakpoint into the generated code
// method?
bool ciMethod::break_at_execute() {
check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method());
return CompilerOracle::should_break_at(mh);
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::has_option // ciMethod::has_option
// //
@ -1101,20 +1055,12 @@ bool ciMethod::has_option(const char* option) {
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::has_option_value // ciMethod::has_option_value
// //
template<typename T> bool ciMethod::has_option_value(const char* option, double& value) {
bool ciMethod::has_option_value(const char* option, T& value) {
check_is_loaded(); check_is_loaded();
VM_ENTRY_MARK; VM_ENTRY_MARK;
methodHandle mh(THREAD, get_Method()); methodHandle mh(THREAD, get_Method());
return CompilerOracle::has_option_value(mh, option, value); return CompilerOracle::has_option_value(mh, option, value);
} }
// Explicit instantiation for all OptionTypes supported.
template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
template bool ciMethod::has_option_value<double>(const char* option, double& value);
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::can_be_compiled // ciMethod::can_be_compiled
// //

View file

@ -104,8 +104,6 @@ class ciMethod : public ciMetadata {
void load_code(); void load_code();
void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
bool ensure_method_data(methodHandle h_m); bool ensure_method_data(methodHandle h_m);
void code_at_put(int bci, Bytecodes::Code code) { void code_at_put(int bci, Bytecodes::Code code) {
@ -120,6 +118,8 @@ class ciMethod : public ciMetadata {
void assert_call_type_ok(int bci); void assert_call_type_ok(int bci);
public: public:
void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
// Basic method information. // Basic method information.
ciFlags flags() const { check_is_loaded(); return _flags; } ciFlags flags() const { check_is_loaded(); return _flags; }
ciSymbol* name() const { return _name; } ciSymbol* name() const { return _name; }
@ -265,14 +265,8 @@ class ciMethod : public ciMetadata {
// Find the proper vtable index to invoke this method. // Find the proper vtable index to invoke this method.
int resolve_vtable_index(ciKlass* caller, ciKlass* receiver); int resolve_vtable_index(ciKlass* caller, ciKlass* receiver);
// Compilation directives
bool should_inline();
bool should_not_inline();
bool should_print_assembly();
bool break_at_execute();
bool has_option(const char *option); bool has_option(const char *option);
template<typename T> bool has_option_value(const char* option, double& value);
bool has_option_value(const char* option, T& value);
bool can_be_compiled(); bool can_be_compiled();
bool can_be_osr_compiled(int entry_bci); bool can_be_osr_compiled(int entry_bci);
void set_not_compilable(const char* reason = NULL); void set_not_compilable(const char* reason = NULL);

View file

@ -417,36 +417,10 @@ int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) {
} }
} }
bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method, const methodHandle& compilation_context) { bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
vmIntrinsics::ID id = method->intrinsic_id(); vmIntrinsics::ID id = method->intrinsic_id();
assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
// Check if the intrinsic corresponding to 'method' has been disabled on
// the command line by using the DisableIntrinsic flag (either globally
// or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
// for details).
// Usually, the compilation context is the caller of the method 'method'.
// The only case when for a non-recursive method 'method' the compilation context
// is not the caller of the 'method' (but it is the method itself) is
// java.lang.ref.Referene::get.
// For java.lang.ref.Reference::get, the intrinsic version is used
// instead of the compiled version so that the value in the referent
// field can be registered by the G1 pre-barrier code. The intrinsified
// version of Reference::get also adds a memory barrier to prevent
// commoning reads from the referent field across safepoint since GC
// can change the referent field's value. See Compile::Compile()
// in src/share/vm/opto/compile.cpp or
// GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
// for more details.
ccstr disable_intr = NULL;
if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
(!compilation_context.is_null() &&
CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
) {
return true;
}
// -XX:-InlineNatives disables nearly all intrinsics except the ones listed in // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
// the following switch statement. // the following switch statement.
if (!InlineNatives) { if (!InlineNatives) {

View file

@ -203,6 +203,10 @@
\ \
/* Concurrency support */ \ /* Concurrency support */ \
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \ template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
template(java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl") \
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater") \
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \ template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \
\ \
/* class symbols needed by intrinsics */ \ /* class symbols needed by intrinsics */ \
@ -1404,7 +1408,7 @@ public:
// Returns true if a compiler intrinsic is disabled by command-line flags // Returns true if a compiler intrinsic is disabled by command-line flags
// and false otherwise. // and false otherwise.
static bool is_disabled_by_flags(const methodHandle& method, const methodHandle& compilation_context); static bool is_disabled_by_flags(const methodHandle& method);
}; };
#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP

View file

@ -32,7 +32,7 @@
#include "compiler/abstractCompiler.hpp" #include "compiler/abstractCompiler.hpp"
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp" #include "compiler/compilerDirectives.hpp"
#include "compiler/disassembler.hpp" #include "compiler/disassembler.hpp"
#include "interpreter/bytecode.hpp" #include "interpreter/bytecode.hpp"
#include "oops/methodData.hpp" #include "oops/methodData.hpp"
@ -582,9 +582,6 @@ nmethod* nmethod::new_native_nmethod(const methodHandle& method,
basic_lock_owner_sp_offset, basic_lock_owner_sp_offset,
basic_lock_sp_offset, oop_maps); basic_lock_sp_offset, oop_maps);
NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm));
if ((PrintAssembly || CompilerOracle::should_print(method)) && nm != NULL) {
Disassembler::decode(nm);
}
} }
// verify nmethod // verify nmethod
debug_only(if (nm) nm->verify();) // might block debug_only(if (nm) nm->verify();) // might block
@ -666,9 +663,6 @@ nmethod* nmethod::new_nmethod(const methodHandle& method,
} }
} }
NOT_PRODUCT(if (nm != NULL) note_java_nmethod(nm)); NOT_PRODUCT(if (nm != NULL) note_java_nmethod(nm));
if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
Disassembler::decode(nm);
}
} }
} }
// Do verification and logging outside CodeCache_lock. // Do verification and logging outside CodeCache_lock.
@ -908,13 +902,6 @@ nmethod::nmethod(
_method->is_static() == (entry_point() == _verified_entry_point), _method->is_static() == (entry_point() == _verified_entry_point),
" entry points must be same for static methods and vice versa"); " entry points must be same for static methods and vice versa");
} }
bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
|| CompilerOracle::should_print(_method)
|| CompilerOracle::has_option_string(_method, "PrintNMethods");
if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
print_nmethod(printnmethods);
}
} }
// Print a short set of xml attributes to identify this nmethod. The // Print a short set of xml attributes to identify this nmethod. The

View file

@ -26,6 +26,7 @@
#define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP #define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
#include "ci/compilerInterface.hpp" #include "ci/compilerInterface.hpp"
#include "compiler/compilerDirectives.hpp"
typedef void (*initializer)(void); typedef void (*initializer)(void);
@ -114,36 +115,33 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
// Determine if the current compiler provides an intrinsic // Determine if the current compiler provides an intrinsic
// for method 'method'. An intrinsic is available if: // for method 'method'. An intrinsic is available if:
// - the intrinsic is enabled (by using the appropriate command-line flag) and // - the intrinsic is enabled (by using the appropriate command-line flag,
// the command-line compile ommand, or a compiler directive)
// - the platform on which the VM is running supports the intrinsic // - the platform on which the VM is running supports the intrinsic
// (i.e., the platform provides the instructions necessary for the compiler // (i.e., the platform provides the instructions necessary for the compiler
// to generate the intrinsic code). // to generate the intrinsic code).
// //
// The second parameter, 'compilation_context', is needed to implement functionality // The directive provides the compilation context and includes pre-evaluated values
// related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can // dependent on VM flags, compile commands, and compiler directives.
// be used to prohibit the compilers to use an intrinsic. There are three ways to
// disable an intrinsic using the DisableIntrinsic flag:
// //
// (1) -XX:DisableIntrinsic=_hashCode,_getClass // Usually, the compilation context is the caller of the method 'method'.
// Disables intrinsification of _hashCode and _getClass globally // The only case when for a non-recursive method 'method' the compilation context
// (i.e., the intrinsified version the methods will not be used at all). // is not the caller of the 'method' (but it is the method itself) is
// (2) -XX:CompileCommand=option,aClass::aMethod,ccstr,DisableIntrinsic,_hashCode // java.lang.ref.Referene::get.
// Disables intrinsification of _hashCode if it is called from // For java.lang.ref.Reference::get, the intrinsic version is used
// aClass::aMethod (but not for any other call site of _hashCode) // instead of the compiled version so that the value in the referent
// (3) -XX:CompileCommand=option,java.lang.ref.Reference::get,ccstr,DisableIntrinsic,_Reference_get // field can be registered by the G1 pre-barrier code. The intrinsified
// Some methods are not compiled by C2. Instead, the C2 compiler // version of Reference::get also adds a memory barrier to prevent
// returns directly the intrinsified version of these methods. // commoning reads from the referent field across safepoint since GC
// The command above forces C2 to compile _Reference_get, but // can change the referent field's value. See Compile::Compile()
// allows using the intrinsified version of _Reference_get at all // in src/share/vm/opto/compile.cpp or
// other call sites. // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
// // for more details.
// From the modes above, (1) disable intrinsics globally, (2) and (3)
// disable intrinsics on a per-method basis. In cases (2) and (3) the virtual bool is_intrinsic_available(const methodHandle& method, DirectiveSet* directive) {
// compilation context is aClass::aMethod and java.lang.ref.Reference::get,
// respectively.
virtual bool is_intrinsic_available(const methodHandle& method, const methodHandle& compilation_context) {
return is_intrinsic_supported(method) && return is_intrinsic_supported(method) &&
!vmIntrinsics::is_disabled_by_flags(method, compilation_context); !directive->is_intrinsic_disabled(method) &&
!vmIntrinsics::is_disabled_by_flags(method);
} }
// Determines if an intrinsic is supported by the compiler, that is, // Determines if an intrinsic is supported by the compiler, that is,
@ -176,7 +174,7 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
void set_state (int state); void set_state (int state);
void set_shut_down () { set_state(shut_down); } void set_shut_down () { set_state(shut_down); }
// Compilation entry point for methods // Compilation entry point for methods
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci) { virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
ShouldNotReachHere(); ShouldNotReachHere();
} }

View file

@ -29,6 +29,7 @@
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp" #include "compiler/compilerOracle.hpp"
#include "compiler/directivesParser.hpp"
#include "interpreter/linkResolver.hpp" #include "interpreter/linkResolver.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "oops/methodData.hpp" #include "oops/methodData.hpp"
@ -202,10 +203,22 @@ class CompilationLog : public StringEventLog {
static CompilationLog* _compilation_log = NULL; static CompilationLog* _compilation_log = NULL;
void compileBroker_init() { bool compileBroker_init() {
if (LogEvents) { if (LogEvents) {
_compilation_log = new CompilationLog(); _compilation_log = new CompilationLog();
} }
// init directives stack, adding default directive
DirectivesStack::init();
if (DirectivesParser::has_file()) {
return DirectivesParser::parse_from_flag();
} else if (PrintCompilerDirectives) {
// Print default directive even when no other was added
DirectivesStack::print(tty);
}
return true;
} }
CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
@ -1180,12 +1193,16 @@ bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int os
return true; return true;
} }
// Breaking the abstraction - directives are only used inside a compilation otherwise.
DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
bool excluded = directive->ExcludeOption;
DirectivesStack::release(directive);
// The method may be explicitly excluded by the user. // The method may be explicitly excluded by the user.
bool quietly;
double scale; double scale;
if (CompilerOracle::should_exclude(method, quietly) if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
|| (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) { bool quietly = CompilerOracle::should_exclude_quietly();
if (!quietly) { if (PrintCompilation && !quietly) {
// This does not happen quietly... // This does not happen quietly...
ResourceMark rm; ResourceMark rm;
tty->print("### Excluding %s:%s", tty->print("### Excluding %s:%s",
@ -1194,7 +1211,7 @@ bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int os
method->print_short_name(tty); method->print_short_name(tty);
tty->cr(); tty->cr();
} }
method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompileCommand"); method->set_not_compilable(comp_level, !quietly, "excluded by CompileCommand");
} }
return false; return false;
@ -1357,7 +1374,6 @@ bool CompileBroker::init_compiler_runtime() {
ThreadInVMfromNative tv(thread); ThreadInVMfromNative tv(thread);
ResetNoHandleMark rnhm; ResetNoHandleMark rnhm;
if (!comp->is_shark()) { if (!comp->is_shark()) {
// Perform per-thread and global initializations // Perform per-thread and global initializations
comp->initialize(); comp->initialize();
@ -1629,6 +1645,10 @@ void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, Even
} }
} }
int DirectivesStack::_depth = 0;
CompilerDirectives* DirectivesStack::_top = NULL;
CompilerDirectives* DirectivesStack::_bottom = NULL;
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// CompileBroker::invoke_compiler_on_method // CompileBroker::invoke_compiler_on_method
// //
@ -1655,16 +1675,20 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
bool should_log = (thread->log() != NULL); bool should_log = (thread->log() != NULL);
bool should_break = false; bool should_break = false;
int task_level = task->comp_level(); int task_level = task->comp_level();
// Look up matching directives
DirectiveSet* directive = DirectivesStack::getMatchingDirective(task->method(), compiler(task_level));
should_break = directive->BreakAtExecuteOption || task->check_break_at_flags();
if (should_log && !directive->LogOption) {
should_log = false;
}
{ {
// create the handle inside it's own block so it can't // create the handle inside it's own block so it can't
// accidentally be referenced once the thread transitions to // accidentally be referenced once the thread transitions to
// native. The NoHandleMark before the transition should catch // native. The NoHandleMark before the transition should catch
// any cases where this occurs in the future. // any cases where this occurs in the future.
methodHandle method(thread, task->method()); methodHandle method(thread, task->method());
should_break = check_break_at(method, compile_id, is_osr);
if (should_log && !CompilerOracle::should_log(method)) {
should_log = false;
}
assert(!method->is_native(), "no longer compile natives"); assert(!method->is_native(), "no longer compile natives");
// Save information about this method in case of failure. // Save information about this method in case of failure.
@ -1732,7 +1756,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
locker.wait(Mutex::_no_safepoint_check_flag); locker.wait(Mutex::_no_safepoint_check_flag);
} }
} }
comp->compile_method(&ci_env, target, osr_bci); comp->compile_method(&ci_env, target, osr_bci, directive);
} }
if (!ci_env.failing() && task->code() == NULL) { if (!ci_env.failing() && task->code() == NULL) {
@ -1762,6 +1786,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
post_compile(thread, task, event, !ci_env.failing(), &ci_env); post_compile(thread, task, event, !ci_env.failing(), &ci_env);
} }
DirectivesStack::release(directive);
pop_jni_handle_block(); pop_jni_handle_block();
methodHandle method(thread, task->method()); methodHandle method(thread, task->method());
@ -1947,21 +1972,6 @@ void CompileBroker::pop_jni_handle_block() {
JNIHandleBlock::release_block(compile_handles, thread); // may block JNIHandleBlock::release_block(compile_handles, thread); // may block
} }
// ------------------------------------------------------------------
// CompileBroker::check_break_at
//
// Should the compilation break at the current compilation.
bool CompileBroker::check_break_at(const methodHandle& method, int compile_id, bool is_osr) {
if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
return true;
} else if( CompilerOracle::should_break_at(method) ) { // break when compiling
return true;
} else {
return (compile_id == CIBreakAt);
}
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// CompileBroker::collect_statistics // CompileBroker::collect_statistics
// //

View file

@ -28,8 +28,10 @@
#include "ci/compilerInterface.hpp" #include "ci/compilerInterface.hpp"
#include "compiler/abstractCompiler.hpp" #include "compiler/abstractCompiler.hpp"
#include "compiler/compileTask.hpp" #include "compiler/compileTask.hpp"
#include "compiler/compilerDirectives.hpp"
#include "runtime/perfData.hpp" #include "runtime/perfData.hpp"
#include "trace/tracing.hpp" #include "trace/tracing.hpp"
#include "utilities/stack.hpp"
class nmethod; class nmethod;
class nmethodLocker; class nmethodLocker;
@ -129,7 +131,6 @@ public:
~CompileTaskWrapper(); ~CompileTaskWrapper();
}; };
// Compilation // Compilation
// //
// The broker for all compilation requests. // The broker for all compilation requests.
@ -238,7 +239,6 @@ class CompileBroker: AllStatic {
static void set_last_compile(CompilerThread *thread, const methodHandle& method, bool is_osr, int comp_level); static void set_last_compile(CompilerThread *thread, const methodHandle& method, bool is_osr, int comp_level);
static void push_jni_handle_block(); static void push_jni_handle_block();
static void pop_jni_handle_block(); static void pop_jni_handle_block();
static bool check_break_at(const methodHandle& method, int compile_id, bool is_osr);
static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task); static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
static void compile_method_base(const methodHandle& method, static void compile_method_base(const methodHandle& method,
@ -254,6 +254,10 @@ class CompileBroker: AllStatic {
static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread); static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
public: public:
static DirectivesStack* dirstack();
static void set_dirstack(DirectivesStack* stack);
enum { enum {
// The entry bci used for non-OSR compilations. // The entry bci used for non-OSR compilations.
standard_entry_bci = InvocationEntryBci standard_entry_bci = InvocationEntryBci
@ -267,6 +271,7 @@ class CompileBroker: AllStatic {
static bool compilation_is_in_queue(const methodHandle& method); static bool compilation_is_in_queue(const methodHandle& method);
static void print_compile_queues(outputStream* st); static void print_compile_queues(outputStream* st);
static void print_directives(outputStream* st);
static int queue_size(int comp_level) { static int queue_size(int comp_level) {
CompileQueue *q = compile_queue(comp_level); CompileQueue *q = compile_queue(comp_level);
return q != NULL ? q->size() : 0; return q != NULL ? q->size() : 0;

View file

@ -26,6 +26,7 @@
#include "compiler/compileTask.hpp" #include "compiler/compileTask.hpp"
#include "compiler/compileLog.hpp" #include "compiler/compileLog.hpp"
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "compiler/compilerDirectives.hpp"
CompileTask* CompileTask::_task_free_list = NULL; CompileTask* CompileTask::_task_free_list = NULL;
#ifdef ASSERT #ifdef ASSERT
@ -371,6 +372,19 @@ void CompileTask::log_task_done(CompileLog* log) {
log->mark_file_end(); log->mark_file_end();
} }
// ------------------------------------------------------------------
// CompileTask::check_break_at_flags
bool CompileTask::check_break_at_flags() {
int compile_id = this->_compile_id;
bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci);
if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
return true;
} else {
return (compile_id == CIBreakAt);
}
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// CompileTask::print_inlining // CompileTask::print_inlining
void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) { void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {

View file

@ -0,0 +1,560 @@
/*
* Copyright (c) 1998, 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.
*
*/
#include "precompiled.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciUtilities.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compilerDirectives.hpp"
#include "compiler/compilerOracle.hpp"
CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) {
_c1_store = new DirectiveSet(this);
_c2_store = new DirectiveSet(this);
};
CompilerDirectives::~CompilerDirectives() {
if (_c1_store != NULL) {
delete _c1_store;
}
if (_c2_store != NULL) {
delete _c2_store;
}
// remove all linked method matchers
BasicMatcher* tmp = _match;
while (tmp != NULL) {
BasicMatcher* next = tmp->next();
delete tmp;
tmp = next;
}
}
void CompilerDirectives::print(outputStream* st) {
assert(DirectivesStack_lock->owned_by_self(), "");
if (_match != NULL) {
st->cr();
st->print("Directive:");
if (is_default_directive()) {
st->print_cr(" (default)");
} else {
st->cr();
}
st->print(" matching: ");
_match->print(st);
BasicMatcher* tmp = _match->next();
while (tmp != NULL) {
st->print(", ");
tmp->print(st);
tmp = tmp->next();
}
st->cr();
} else {
assert(0, "There should always be a match");
}
if (_c1_store != NULL) {
st->print_cr(" c1 directives:");
_c1_store->print(st);
}
if (_c2_store != NULL) {
st->cr();
st->print_cr(" c2 directives:");
_c2_store->print(st);
}
//---
}
void CompilerDirectives::finalize() {
if (_c1_store != NULL) {
_c1_store->finalize();
}
if (_c2_store != NULL) {
_c2_store->finalize();
}
}
void DirectiveSet::finalize() {
// if any flag has been modified - set directive as enabled
// unless it already has been explicitly set.
if (!_modified[EnableIndex]) {
if (_inlinematchers != NULL) {
EnableOption = true;
return;
}
int i;
for (i = 0; i < number_of_flags; i++) {
if (_modified[i]) {
EnableOption = true;
return;
}
}
}
}
CompilerDirectives* CompilerDirectives::next() {
return _next;
}
bool CompilerDirectives::match(methodHandle method) {
if (is_default_directive()) {
return true;
}
if (method == NULL) {
return false;
}
if (_match->match(method)) {
return true;
}
return false;
}
bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
if (bm == NULL) {
assert(error_msg != NULL, "Must have error message");
return false;
} else {
bm->set_next(_match);
_match = bm;
return true;
}
}
void CompilerDirectives::inc_refcount() {
assert(DirectivesStack_lock->owned_by_self(), "");
_ref_count++;
}
void CompilerDirectives::dec_refcount() {
assert(DirectivesStack_lock->owned_by_self(), "");
_ref_count--;
}
int CompilerDirectives::refcount() {
assert(DirectivesStack_lock->owned_by_self(), "");
return _ref_count;
}
DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
assert(DirectivesStack_lock->owned_by_self(), "");
inc_refcount(); // The compiling thread is responsible to decrement this when finished.
if (comp == NULL) { // Xint
return _c1_store;
} else if (comp->is_c2()) {
return _c2_store;
} else if (comp->is_c1()) {
return _c1_store;
} else if (comp->is_shark()) {
return NULL;
} else if (comp->is_jvmci()) {
return NULL;
}
ShouldNotReachHere();
return NULL;
}
// In the list of disabled intrinsics, the ID of the disabled intrinsics can separated:
// - by ',' (if -XX:DisableIntrinsic is used once when invoking the VM) or
// - by '\n' (if -XX:DisableIntrinsic is used multiple times when invoking the VM) or
// - by ' ' (if DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
//
// To simplify the processing of the list, the canonicalize_disableintrinsic() method
// returns a new copy of the list in which '\n' and ' ' is replaced with ','.
ccstrlist DirectiveSet::canonicalize_disableintrinsic(ccstrlist option_value) {
char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
int i = 0;
char current;
while ((current = option_value[i]) != '\0') {
if (current == '\n' || current == ' ') {
canonicalized_list[i] = ',';
} else {
canonicalized_list[i] = current;
}
i++;
}
canonicalized_list[i] = '\0';
return canonicalized_list;
}
DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
compilerdirectives_common_flags(init_defaults_definition)
compilerdirectives_c2_flags(init_defaults_definition)
compilerdirectives_c1_flags(init_defaults_definition)
memset(_modified, 0, sizeof _modified);
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
this->DisableIntrinsicOption = canonicalize_disableintrinsic(DisableIntrinsic);
}
DirectiveSet::~DirectiveSet() {
// remove all linked methodmatchers
InlineMatcher* tmp = _inlinematchers;
while (tmp != NULL) {
InlineMatcher* next = tmp->next();
delete tmp;
tmp = next;
}
// When constructed, DirectiveSet canonicalizes the DisableIntrinsic flag
// into a new string. Therefore, that string is deallocated when
// the DirectiveSet is destroyed.
assert(this->DisableIntrinsicOption != NULL, "");
FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
}
// Backward compatibility for CompileCommands
// Breaks the abstraction and causes lots of extra complexity
// - if some option is changed we need to copy directiveset since it no longer can be shared
// - Need to free copy after use
// - Requires a modified bit so we don't overwrite options that is set by directives
DirectiveSet* DirectiveSet::compilecommand_compatibility_init(methodHandle method) {
// Early bail out - checking all options is expensive - we rely on them not being used
// Only set a flag if it has not been modified and value changes.
// Only copy set if a flag needs to be set
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
DirectiveSet* set = DirectiveSet::clone(this);
bool changed = false; // Track if we actually change anything
// All CompileCommands are not equal so this gets a bit verbose
// When CompileCommands have been refactored less clutter will remain.
if (CompilerOracle::should_break_at(method)) {
if (!_modified[BreakAtCompileIndex]) {
set->BreakAtCompileOption = true;
changed = true;
}
if (!_modified[BreakAtExecuteIndex]) {
set->BreakAtExecuteOption = true;
changed = true;
}
}
if (CompilerOracle::should_log(method)) {
if (!_modified[LogIndex]) {
set->LogOption = true;
changed = true;
}
}
if (CompilerOracle::should_print(method)) {
if (!_modified[PrintAssemblyIndex]) {
set->PrintAssemblyOption = true;
changed = true;
}
}
// Exclude as in should not compile == Enabled
if (CompilerOracle::should_exclude(method)) {
if (!_modified[ExcludeIndex]) {
set->ExcludeOption = true;
changed = true;
}
}
// inline and dontinline (including exclude) are implemented in the directiveset accessors
#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set->name##Option = v; changed = true;} }
compilerdirectives_common_flags(init_default_cc)
compilerdirectives_c2_flags(init_default_cc)
compilerdirectives_c1_flags(init_default_cc)
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
ccstrlist option_value;
if (!_modified[DisableIntrinsicIndex] &&
CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
set->DisableIntrinsicOption = canonicalize_disableintrinsic(option_value);
}
if (!changed) {
// We didn't actually update anything, discard.
delete set;
} else {
// We are returning a (parentless) copy. The originals parent don't need to account for this.
DirectivesStack::release(this);
return set;
}
}
// Nothing changed
return this;
}
CompilerDirectives* DirectiveSet::directive() {
assert(_directive != NULL, "Must have been initialized");
return _directive;
}
bool DirectiveSet::matches_inline(methodHandle method, int inline_action) {
if (_inlinematchers != NULL) {
if (_inlinematchers->match(method, InlineMatcher::force_inline)) {
return true;
}
}
return false;
}
bool DirectiveSet::should_inline(ciMethod* inlinee) {
inlinee->check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, inlinee->get_Method());
if (matches_inline(mh, InlineMatcher::force_inline)) {
return true;
}
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_inline(mh)) {
return true;
}
return false;
}
bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
inlinee->check_is_loaded();
VM_ENTRY_MARK;
methodHandle mh(THREAD, inlinee->get_Method());
if (matches_inline(mh, InlineMatcher::dont_inline)) {
return true;
}
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_not_inline(mh)) {
return true;
}
return false;
}
bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
if (m != NULL) {
// add matcher last in chain - the order is significant
append_inline(m);
return true;
} else {
assert(error_msg != NULL, "Error message must be set");
return false;
}
}
void DirectiveSet::append_inline(InlineMatcher* m) {
if (_inlinematchers == NULL) {
_inlinematchers = m;
return;
}
InlineMatcher* tmp = _inlinematchers;
while (tmp->next() != NULL) {
tmp = tmp->next();
}
tmp->set_next(m);
}
void DirectiveSet::print_inline(outputStream* st) {
if (_inlinematchers == NULL) {
st->print_cr(" inline: -");
} else {
st->print(" inline: ");
_inlinematchers->print(st);
InlineMatcher* tmp = _inlinematchers->next();
while (tmp != NULL) {
st->print(", ");
tmp->print(st);
tmp = tmp->next();
}
st->cr();
}
}
bool DirectiveSet::is_intrinsic_disabled(methodHandle method) {
vmIntrinsics::ID id = method->intrinsic_id();
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
ResourceMark rm;
// Create a copy of the string that contains the list of disabled
// intrinsics. The copy is created because the string
// will be modified by strtok(). Then, the list is tokenized with
// ',' as a separator.
size_t length = strlen(DisableIntrinsicOption);
char* local_list = NEW_RESOURCE_ARRAY(char, length + 1);
strncpy(local_list, DisableIntrinsicOption, length + 1);
char* token = strtok(local_list, ",");
while (token != NULL) {
if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
return true;
} else {
token = strtok(NULL, ",");
}
}
return false;
}
DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
DirectiveSet* set = new DirectiveSet(NULL);
memcpy(set->_modified, src->_modified, sizeof(src->_modified));
InlineMatcher* tmp = src->_inlinematchers;
while (tmp != NULL) {
set->append_inline(tmp->clone());
tmp = tmp->next();
}
#define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
compilerdirectives_common_flags(copy_members_definition)
compilerdirectives_c2_flags(copy_members_definition)
compilerdirectives_c1_flags(copy_members_definition)
// Create a local copy of the DisableIntrinsicOption.
assert(src->DisableIntrinsicOption != NULL, "");
size_t len = strlen(src->DisableIntrinsicOption) + 1;
char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
strncpy(s, src->DisableIntrinsicOption, len);
assert(s[len-1] == '\0', "");
set->DisableIntrinsicOption = s;
return set;
}
// Create a new dirstack and push a default directive
void DirectivesStack::init() {
CompilerDirectives* _default_directives = new CompilerDirectives();
char str[] = "*.*";
const char* error_msg = NULL;
_default_directives->add_match(str, error_msg);
#ifdef COMPILER1
_default_directives->_c1_store->EnableOption = true;
#endif
#ifdef COMPILER2
_default_directives->_c2_store->EnableOption = true;
#endif
assert(error_msg == NULL, "Must succeed.");
push(_default_directives);
}
DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
assert(_bottom != NULL, "Must never be empty");
return _bottom->get_for(comp);
}
void DirectivesStack::push(CompilerDirectives* directive) {
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
directive->inc_refcount();
if (_top == NULL) {
assert(_bottom == NULL, "There can only be one default directive");
_bottom = directive; // default directive, can never be removed.
}
directive->set_next(_top);
_top = directive;
_depth++;
}
void DirectivesStack::pop() {
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
pop_inner();
}
void DirectivesStack::pop_inner() {
assert(DirectivesStack_lock->owned_by_self(), "");
if (_top->next() == NULL) {
return; // Do nothing - don't allow an empty stack
}
CompilerDirectives* tmp = _top;
_top = _top->next();
_depth--;
DirectivesStack::release(tmp);
}
void DirectivesStack::clear() {
// holding the lock during the whole operation ensuring consistent result
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
while (_top->next() != NULL) {
pop_inner();
}
}
void DirectivesStack::print(outputStream* st) {
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
CompilerDirectives* tmp = _top;
while (tmp != NULL) {
tmp->print(st);
tmp = tmp->next();
st->cr();
}
}
void DirectivesStack::release(DirectiveSet* set) {
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
if (set->is_exclusive_copy()) {
// Old CompilecCmmands forced us to create an exclusive copy
delete set;
} else {
assert(set->directive() != NULL, "");
release(set->directive());
}
}
void DirectivesStack::release(CompilerDirectives* dir) {
assert(DirectivesStack_lock->owned_by_self(), "");
dir->dec_refcount();
if (dir->refcount() == 0) {
delete dir;
}
}
DirectiveSet* DirectivesStack::getMatchingDirective(methodHandle method, AbstractCompiler *comp) {
assert(_depth > 0, "Must never be empty");
CompilerDirectives* dir = _top;
assert(dir != NULL, "Must be initialized");
DirectiveSet* match = NULL;
{
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
while (dir != NULL) {
if (dir->is_default_directive() || dir->match(method)) {
match = dir->get_for(comp);
if (match == NULL) {
// temporary workaround for compilers without directives.
if (dir->is_default_directive()) {
// default dir is always enabled
// match c1 store - it contains all common flags even if C1 is unavailable
match = dir->_c1_store;
break;
}
}
if (match->EnableOption) {
// The directiveSet for this compile is also enabled -> success
break;
}
}
dir = dir->next();
}
}
guarantee(match != NULL, "There should always be a default directive that matches");
// Check for legacy compile commands update, without DirectivesStack_lock
return match->compilecommand_compatibility_init(method);
}

View file

@ -0,0 +1,189 @@
/*
* Copyright (c) 1998, 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.
*
*/
#ifndef SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
#define SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
#include "ci/ciMetadata.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciUtilities.hpp"
#include "compiler/methodMatcher.hpp"
#include "compiler/compilerOracle.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/exceptions.hpp"
// Directives flag name, type, default value, compile command name
#define compilerdirectives_common_flags(cflags) \
cflags(Enable, bool, false, X) \
cflags(Exclude, bool, false, X) \
cflags(BreakAtExecute, bool, false, X) \
cflags(BreakAtCompile, bool, false, X) \
cflags(Log, bool, false, X) \
cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \
cflags(PrintInlining, bool, PrintInlining, PrintInlining) \
cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \
cflags(ReplayInline, bool, false, ReplayInline) \
cflags(DumpReplay, bool, false, DumpReplay) \
cflags(DumpInline, bool, false, DumpInline) \
cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic)
#ifdef COMPILER1
#define compilerdirectives_c1_flags(cflags)
#else
#define compilerdirectives_c1_flags(cflags)
#endif
#ifdef COMPILER2
#define compilerdirectives_c2_flags(cflags) \
cflags(BlockLayoutByFrequency, bool, BlockLayoutByFrequency, BlockLayoutByFrequency) \
cflags(PrintOptoAssembly, bool, PrintOptoAssembly, PrintOptoAssembly) \
cflags(PrintIntrinsics, bool, PrintIntrinsics, PrintIntrinsics) \
cflags(TraceOptoPipelining, bool, false, TraceOptoPipelining) \
cflags(TraceOptoOutput, bool, false, TraceOptoOutput) \
cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \
cflags(Vectorize, bool, false, Vectorize) \
cflags(VectorizeDebug, bool, false, VectorizeDebug) \
cflags(CloneMapDebug, bool, false, CloneMapDebug) \
cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
NOT_PRODUCT( cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel)) \
cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit)
#else
#define compilerdirectives_c2_flags(cflags)
#endif
class CompilerDirectives;
class DirectiveSet;
class DirectivesStack : AllStatic {
private:
static CompilerDirectives* _top;
static CompilerDirectives* _bottom;
static int _depth;
static void pop_inner(); // no lock version of pop
public:
static void init();
static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
static void push(CompilerDirectives* directive);
static void pop();
static void clear();
static void print(outputStream* st);
static void release(DirectiveSet* set);
static void release(CompilerDirectives* dir);
};
class DirectiveSet : public CHeapObj<mtCompiler> {
private:
InlineMatcher* _inlinematchers;
CompilerDirectives* _directive;
static ccstrlist canonicalize_disableintrinsic(ccstrlist option_value);
public:
DirectiveSet(CompilerDirectives* directive);
~DirectiveSet();
CompilerDirectives* directive();
bool parse_and_add_inline(char* str, const char*& error_msg);
void append_inline(InlineMatcher* m);
bool should_inline(ciMethod* inlinee);
bool should_not_inline(ciMethod* inlinee);
void print_inline(outputStream* st);
DirectiveSet* compilecommand_compatibility_init(methodHandle method);
bool is_exclusive_copy() { return _directive == NULL; }
bool matches_inline(methodHandle method, int inline_action);
static DirectiveSet* clone(DirectiveSet const* src);
bool is_intrinsic_disabled(methodHandle method);
void finalize();
typedef enum {
#define enum_of_flags(name, type, dvalue, cc_flag) name##Index,
compilerdirectives_common_flags(enum_of_flags)
compilerdirectives_c2_flags(enum_of_flags)
compilerdirectives_c1_flags(enum_of_flags)
number_of_flags
} flags;
bool _modified[number_of_flags];
#define flag_store_definition(name, type, dvalue, cc_flag) type name##Option;
compilerdirectives_common_flags(flag_store_definition)
compilerdirectives_c2_flags(flag_store_definition)
compilerdirectives_c1_flags(flag_store_definition)
// Casting to get the same function signature for all setters. Used from parser.
#define set_function_definition(name, type, dvalue, cc_flag) void set_##name(void* value) { type val = *(type*)value; name##Option = val; _modified[name##Index] = 1; }
compilerdirectives_common_flags(set_function_definition)
compilerdirectives_c2_flags(set_function_definition)
compilerdirectives_c1_flags(set_function_definition)
void print_intx(outputStream* st, ccstr n, intx v, bool mod) { if (mod) { st->print("%s:" INTX_FORMAT " ", n, v); } }
void print_bool(outputStream* st, ccstr n, bool v, bool mod) { if (mod) { st->print("%s:%s ", n, v ? "true" : "false"); } }
void print_double(outputStream* st, ccstr n, double v, bool mod) { if (mod) { st->print("%s:%f ", n, v); } }
void print_ccstr(outputStream* st, ccstr n, ccstr v, bool mod) { if (mod) { st->print("%s:%s ", n, v); } }
void print_ccstrlist(outputStream* st, ccstr n, ccstr v, bool mod) { print_ccstr(st, n, v, mod); }
void print(outputStream* st) {
print_inline(st);
st->print(" ");
#define print_function_definition(name, type, dvalue, cc_flag) print_##type(st, #name, this->name##Option, true);//(bool)_modified[name##Index]);
compilerdirectives_common_flags(print_function_definition)
compilerdirectives_c2_flags(print_function_definition)
compilerdirectives_c1_flags(print_function_definition)
st->cr();
}
};
class CompilerDirectives : public CHeapObj<mtCompiler> {
private:
CompilerDirectives* _next;
BasicMatcher* _match;
int _ref_count;
public:
CompilerDirectives();
~CompilerDirectives();
CompilerDirectives* next();
void set_next(CompilerDirectives* next) {_next = next; }
bool match(methodHandle method);
BasicMatcher* match() { return _match; }
bool add_match(char* str, const char*& error_msg);
DirectiveSet* get_for(AbstractCompiler *comp);
void print(outputStream* st);
bool is_default_directive() { return _next == NULL; }
void finalize();
void inc_refcount();
void dec_refcount();
int refcount();
DirectiveSet* _c1_store;
DirectiveSet* _c2_store;
};
#endif // SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP

View file

@ -106,6 +106,7 @@ class TypedMethodOptionMatcher;
static BasicMatcher* lists[OracleCommandCount] = { 0, }; static BasicMatcher* lists[OracleCommandCount] = { 0, };
static TypedMethodOptionMatcher* option_list = NULL; static TypedMethodOptionMatcher* option_list = NULL;
static bool any_set = false;
class TypedMethodOptionMatcher : public MethodMatcher { class TypedMethodOptionMatcher : public MethodMatcher {
private: private:
@ -292,6 +293,7 @@ static void add_option_string(TypedMethodOptionMatcher* matcher,
matcher->init(option, get_type_for<T>(), option_list); matcher->init(option, get_type_for<T>(), option_list);
matcher->set_value<T>(value); matcher->set_value<T>(value);
option_list = matcher; option_list = matcher;
any_set = true;
return; return;
} }
@ -308,7 +310,9 @@ static void add_predicate(OracleCommand command, BasicMatcher* bm) {
} }
bm->set_next(lists[command]); bm->set_next(lists[command]);
lists[command] = bm; lists[command] = bm;
if ((command != DontInlineCommand) && (command != InlineCommand)) {
any_set = true;
}
return; return;
} }
@ -324,6 +328,10 @@ bool CompilerOracle::has_option_value(const methodHandle& method, const char* op
return false; return false;
} }
bool CompilerOracle::has_any_option() {
return any_set;
}
// Explicit instantiation for all OptionTypes supported. // Explicit instantiation for all OptionTypes supported.
template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, const char* option, intx& value); template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, const char* option, intx& value);
template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, const char* option, uintx& value); template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, const char* option, uintx& value);
@ -337,15 +345,10 @@ bool CompilerOracle::has_option_string(const methodHandle& method, const char* o
return value; return value;
} }
bool CompilerOracle::should_exclude(const methodHandle& method, bool& quietly) { bool CompilerOracle::should_exclude(const methodHandle& method) {
quietly = true; if (check_predicate(ExcludeCommand, method)) {
if (lists[ExcludeCommand] != NULL) {
if (lists[ExcludeCommand]->match(method)) {
quietly = _quiet;
return true; return true;
} }
}
if (lists[CompileOnlyCommand] != NULL) { if (lists[CompileOnlyCommand] != NULL) {
return !lists[CompileOnlyCommand]->match(method); return !lists[CompileOnlyCommand]->match(method);
} }
@ -356,8 +359,6 @@ bool CompilerOracle::should_inline(const methodHandle& method) {
return (check_predicate(InlineCommand, method)); return (check_predicate(InlineCommand, method));
} }
// Check both DontInlineCommand and ExcludeCommand here
// - consistent behavior for all compilers
bool CompilerOracle::should_not_inline(const methodHandle& method) { bool CompilerOracle::should_not_inline(const methodHandle& method) {
return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method); return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method);
} }

View file

@ -46,7 +46,8 @@ class CompilerOracle : AllStatic {
static void parse_from_file(); static void parse_from_file();
// Tells whether we to exclude compilation of method // Tells whether we to exclude compilation of method
static bool should_exclude(const methodHandle& method, bool& quietly); static bool should_exclude(const methodHandle& method);
static bool should_exclude_quietly() { return _quiet; }
// Tells whether we want to inline this method // Tells whether we want to inline this method
static bool should_inline(const methodHandle& method); static bool should_inline(const methodHandle& method);
@ -71,6 +72,9 @@ class CompilerOracle : AllStatic {
template<typename T> template<typename T>
static bool has_option_value(const methodHandle& method, const char* option, T& value); static bool has_option_value(const methodHandle& method, const char* option, T& value);
// Fast check if there is any option available that compile control needs to know about
static bool has_any_option();
// Reads from string instead of file // Reads from string instead of file
static void parse_from_string(const char* command_string, void (*parser)(char*)); static void parse_from_string(const char* command_string, void (*parser)(char*));

View file

@ -0,0 +1,726 @@
/*
* 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.
*
*/
#include "precompiled.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/directivesParser.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/os.hpp"
#include <string.h>
void DirectivesParser::push_tmp(CompilerDirectives* dir) {
dir->set_next(_tmp_top);
_tmp_top = dir;
}
CompilerDirectives* DirectivesParser::pop_tmp() {
if (_tmp_top == NULL) {
return NULL;
}
CompilerDirectives* tmp = _tmp_top;
_tmp_top = _tmp_top->next();
tmp->set_next(NULL);
return tmp;
}
bool DirectivesParser::parse_string(const char* text, outputStream* st) {
DirectivesParser cd(text, st);
if (cd.valid()) {
return cd.install_directives();
}
st->flush();
st->print_cr("Parsing of compiler directives failed");
return false;
}
bool DirectivesParser::has_file() {
return CompilerDirectivesFile != NULL;
}
bool DirectivesParser::parse_from_flag() {
return parse_from_file(CompilerDirectivesFile, tty);
}
bool DirectivesParser::parse_from_file(const char* filename, outputStream* st) {
assert(filename != NULL, "Test before calling this");
if (!parse_from_file_inner(filename, st)) {
st->print_cr("Could not load file: %s", filename);
return false;
}
return true;
}
bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream) {
struct stat st;
ResourceMark rm;
if (os::stat(filename, &st) == 0) {
// found file, open it
int file_handle = os::open(filename, 0, 0);
if (file_handle != -1) {
// read contents into resource array
char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
buffer[num_read] = '\0';
// close file
os::close(file_handle);
return parse_string(buffer, stream);
}
}
return false;
}
bool DirectivesParser::install_directives() {
// Pop from internal temporary stack and push to compileBroker.
CompilerDirectives* tmp = pop_tmp();
int i = 0;
while (tmp != NULL) {
i++;
DirectivesStack::push(tmp);
tmp = pop_tmp();
}
if (i == 0) {
_st->print_cr("No directives in file");
return false;
} else {
_st->print_cr("%i compiler directives added", i);
if (PrintCompilerDirectives) {
// Print entire directives stack after new has been pushed.
DirectivesStack::print(_st);
}
return true;
}
}
DirectivesParser::DirectivesParser(const char* text, outputStream* st)
: JSON(text, false, st), depth(0), current_directive(NULL), current_directiveset(NULL), _tmp_top(NULL) {
#ifndef PRODUCT
memset(stack, 0, MAX_DEPTH * sizeof(stack[0]));
#endif
parse();
}
DirectivesParser::~DirectivesParser() {
}
const DirectivesParser::key DirectivesParser::keys[] = {
// name, keytype, allow_array, allowed_mask, set_function
{ "c1", type_c1, 0, mask(type_directives), NULL, UnknownFlagType },
{ "c2", type_c2, 0, mask(type_directives), NULL, UnknownFlagType },
{ "match", type_match, 1, mask(type_directives), NULL, UnknownFlagType },
{ "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
{ "enable", type_enable, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
{ "preset", type_preset, 0, mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
// Global flags
#define common_flag_key(name, type, dvalue, compiler) \
{ #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag},
compilerdirectives_common_flags(common_flag_key)
compilerdirectives_c2_flags(common_flag_key)
compilerdirectives_c1_flags(common_flag_key)
#undef common_flag_key
};
const DirectivesParser::key DirectivesParser::dir_array_key = {
"top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
};
const DirectivesParser::key DirectivesParser::dir_key = {
"top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
};
const DirectivesParser::key DirectivesParser::value_array_key = {
"value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
};
const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) {
for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
if (strncasecmp(keys[i].name, str, len) == 0) {
return &keys[i];
}
}
return NULL;
}
uint DirectivesParser::mask(keytype kt) {
return 1 << (kt + 1);
}
bool DirectivesParser::push_key(const char* str, size_t len) {
bool result = true;
const key* k = lookup_key(str, len);
if (k == NULL) {
// os::strdup
char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
strncpy(s, str, len);
s[len] = '\0';
error(KEY_ERROR, "No such key: '%s'.", s);
FREE_C_HEAP_ARRAY(char, s);
return false;
}
return push_key(k);
}
bool DirectivesParser::push_key(const key* k) {
assert(k->allowedmask != 0, "not allowed anywhere?");
// Exceeding the stack should not be possible with a valid compiler directive,
// and an invalid should abort before this happens
assert(depth < MAX_DEPTH, "exceeded stack depth");
if (depth >= MAX_DEPTH) {
error(INTERNAL_ERROR, "Stack depth exceeded.");
return false;
}
assert(stack[depth] == NULL, "element not nulled, something is wrong");
if (depth == 0 && !(k->allowedmask & 1)) {
error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name);
return false;
}
if (depth > 0) {
const key* prev = stack[depth - 1];
if (!(k->allowedmask & mask(prev->type))) {
error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name);
return false;
}
}
stack[depth] = k;
depth++;
return true;
}
const DirectivesParser::key* DirectivesParser::current_key() {
assert(depth > 0, "getting key from empty stack");
if (depth == 0) {
return NULL;
}
return stack[depth - 1];
}
const DirectivesParser::key* DirectivesParser::pop_key() {
assert(depth > 0, "popping empty stack");
if (depth == 0) {
error(INTERNAL_ERROR, "Popping empty stack.");
return NULL;
}
depth--;
const key* k = stack[depth];
#ifndef PRODUCT
stack[depth] = NULL;
#endif
return k;
}
bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) {
void (DirectiveSet::*test)(void *args);
test = option_key->set;
switch (t) {
case JSON_TRUE:
if (option_key->flag_type != boolFlag) {
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
return false;
} else {
bool val = true;
(set->*test)((void *)&val);
}
break;
case JSON_FALSE:
if (option_key->flag_type != boolFlag) {
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
return false;
} else {
bool val = false;
(set->*test)((void *)&val);
}
break;
case JSON_NUMBER_INT:
if (option_key->flag_type != intxFlag) {
if (option_key->flag_type == doubleFlag) {
double dval = (double)v->int_value;
(set->*test)((void *)&dval);
break;
}
error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]);
return false;
} else {
intx ival = v->int_value;
(set->*test)((void *)&ival);
}
break;
case JSON_NUMBER_FLOAT:
if (option_key->flag_type != doubleFlag) {
error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]);
return false;
} else {
double dval = v->double_value;
(set->*test)((void *)&dval);
}
break;
case JSON_STRING:
if (option_key->flag_type != ccstrFlag && option_key->flag_type != ccstrlistFlag) {
error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]);
return false;
} else {
char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1, mtCompiler);
strncpy(s, v->str.start, v->str.length + 1);
s[v->str.length] = '\0';
(set->*test)((void *)&s);
}
break;
default:
assert(0, "Should not reach here.");
}
return true;
}
bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) {
const key* option_key = pop_key();
const key* enclosing_key = current_key();
if (option_key->type == value_array_key.type) {
// Multi value array, we are really setting the value
// for the key one step further up.
option_key = pop_key();
enclosing_key = current_key();
// Repush option_key and multi value marker, since
// we need to keep them until all multi values are set.
push_key(option_key);
push_key(&value_array_key);
}
switch (option_key->type) {
case type_flag:
{
if (current_directiveset == NULL) {
assert(depth == 2, "Must not have active directive set");
if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) {
return false;
}
if(!set_option_flag(t, v, option_key, current_directive->_c2_store)) {
return false;
}
} else {
assert(depth > 2, "Must have active current directive set");
if (!set_option_flag(t, v, option_key, current_directiveset)) {
return false;
}
}
break;
}
case type_match:
if (t != JSON_STRING) {
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
return false;
}
if (enclosing_key->type != type_directives) {
error(SYNTAX_ERROR, "Match keyword can only exist inside a directive");
return false;
}
{
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
strncpy(s, v->str.start, v->str.length);
s[v->str.length] = '\0';
const char* error_msg = NULL;
if (!current_directive->add_match(s, error_msg)) {
assert (error_msg != NULL, "Must have valid error message");
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
}
FREE_C_HEAP_ARRAY(char, s);
}
break;
case type_inline:
if (t != JSON_STRING) {
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
return false;
}
{
//char* s = strndup(v->str.start, v->str.length);
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
strncpy(s, v->str.start, v->str.length);
s[v->str.length] = '\0';
const char* error_msg = NULL;
if (current_directiveset == NULL) {
if (!current_directive->_c1_store->parse_and_add_inline(s, error_msg)) {
assert (error_msg != NULL, "Must have valid error message");
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
}
if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) {
assert (error_msg != NULL, "Must have valid error message");
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
}
} else {
if (!current_directiveset->parse_and_add_inline(s, error_msg)) {
assert (error_msg != NULL, "Must have valid error message");
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
}
}
FREE_C_HEAP_ARRAY(char, s);
}
break;
case type_c1:
current_directiveset = current_directive->_c1_store;
if (t != JSON_TRUE && t != JSON_FALSE) {
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
return false;
}
break;
case type_c2:
current_directiveset = current_directive->_c2_store;
if (t != JSON_TRUE && t != JSON_FALSE) {
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
return false;
}
break;
case type_enable:
switch (enclosing_key->type) {
case type_c1:
case type_c2:
{
if (t != JSON_TRUE && t != JSON_FALSE) {
error(VALUE_ERROR, "Key of type %s enclosed in a %s key needs a true or false value", option_key->name, enclosing_key->name);
return false;
}
int val = (t == JSON_TRUE);
current_directiveset->set_Enable(&val);
break;
}
case type_directives:
error(VALUE_ERROR, "Enable keyword not available for generic directive");
return false;
default:
error(INTERNAL_ERROR, "Unexpected enclosing type for key %s: %s", option_key->name, enclosing_key->name);
ShouldNotReachHere();
return false;
}
break;
default:
break;
}
return true;
}
bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) {
const key* k;
if (depth == 0) {
switch (t) {
case JSON_ARRAY_BEGIN:
return push_key(&dir_array_key);
case JSON_OBJECT_BEGIN:
// push synthetic dir_array
push_key(&dir_array_key);
assert(depth == 1, "Make sure the stack are aligned with the directives");
break;
default:
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
return false;
}
}
if (depth == 1) {
switch (t) {
case JSON_OBJECT_BEGIN:
// Parsing a new directive.
current_directive = new CompilerDirectives();
return push_key(&dir_key);
case JSON_ARRAY_END:
k = pop_key();
if (k->type != type_dir_array) {
error(SYNTAX_ERROR, "Expected end of directives array");
return false;
}
return true;
default:
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
return false;
}
} else {
switch (t) {
case JSON_OBJECT_BEGIN:
k = current_key();
switch (k->type) {
case type_c1:
current_directiveset = current_directive->_c1_store;
return true;
case type_c2:
current_directiveset = current_directive->_c2_store;
return true;
case type_dir_array:
return push_key(&dir_key);
default:
error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name);
return false;
}
return false;
case JSON_OBJECT_END:
k = pop_key();
switch (k->type) {
case type_c1:
case type_c2:
// This is how we now if options apply to a single or both directive sets
current_directiveset = NULL;
break;
case type_directives:
// Check, finish and push to stack!
if (current_directive->match() == NULL) {
error(INTERNAL_ERROR, "Directive missing required match.");
return false;
}
current_directive->finalize();
push_tmp(current_directive);
current_directive = NULL;
break;
default:
error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
ShouldNotReachHere();
return false;
}
return true;
case JSON_ARRAY_BEGIN:
k = current_key();
if (!(k->allow_array_value)) {
if (k->type == type_dir_array) {
error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
} else {
error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
}
return false;
}
return push_key(&value_array_key);
case JSON_ARRAY_END:
k = pop_key(); // Pop multi value marker
assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
k = pop_key(); // Pop key for option that was set
return true;
case JSON_KEY:
return push_key(v->str.start, v->str.length);
case JSON_STRING:
case JSON_NUMBER_INT:
case JSON_NUMBER_FLOAT:
case JSON_TRUE:
case JSON_FALSE:
case JSON_NULL:
return set_option(t, v);
default:
error(INTERNAL_ERROR, "Unknown JSON type: %d.", t);
ShouldNotReachHere();
return false;
}
}
}
#ifndef PRODUCT
void DirectivesParser::test(const char* text, bool should_pass) {
DirectivesParser cd(text, tty);
if (should_pass) {
assert(cd.valid() == true, "failed on a valid DirectivesParser string");
if (VerboseInternalVMTests) {
tty->print("-- DirectivesParser test passed as expected --\n");
}
} else {
assert(cd.valid() == false, "succeeded on an invalid DirectivesParser string");
if (VerboseInternalVMTests) {
tty->print("-- DirectivesParser test failed as expected --\n");
}
}
}
bool DirectivesParser::test() {
DirectivesParser::test("{}", false);
DirectivesParser::test("[]", true);
DirectivesParser::test("[{}]", false);
DirectivesParser::test("[{},{}]", false);
DirectivesParser::test("{},{}", false);
DirectivesParser::test(
"[" "\n"
" {" "\n"
" match: \"foo/bar.*\"," "\n"
" inline : \"+java/util.*\"," "\n"
" PrintAssembly: true," "\n"
" BreakAtExecute: true," "\n"
" }" "\n"
"]" "\n", true);
DirectivesParser::test(
"[" "\n"
" [" "\n"
" {" "\n"
" match: \"foo/bar.*\"," "\n"
" inline : \"+java/util.*\"," "\n"
" PrintAssembly: true," "\n"
" BreakAtExecute: true," "\n"
" }" "\n"
" ]" "\n"
"]" "\n", false);
/*DirectivesParser::test(
"[" "\n"
" {" "\n"
" match: \"foo/bar.*\"," "\n"
" c1: {"
" PrintIntrinsics: false," "\n"
" }" "\n"
" }" "\n"
"]" "\n", false);*/
DirectivesParser::test(
"[" "\n"
" {" "\n"
" match: \"foo/bar.*\"," "\n"
" c2: {" "\n"
" PrintInlining: false," "\n"
" }" "\n"
" }" "\n"
"]" "\n", true);
DirectivesParser::test(
"[" "\n"
" {" "\n"
" match: \"foo/bar.*\"," "\n"
" PrintInlining: [" "\n"
" true," "\n"
" false" "\n"
" ]," "\n"
" }" "\n"
"]" "\n", false);
DirectivesParser::test(
"[" "\n"
" {"
" // pattern to match against class+method+signature" "\n"
" // leading and trailing wildcard (*) allowed" "\n"
" match: \"foo/bar.*\"," "\n"
"" "\n"
" // override defaults for specified compiler" "\n"
" // we may differentiate between levels too. TBD." "\n"
" c1: {" "\n"
" //override c1 presets " "\n"
" DumpReplay: false," "\n"
" BreakAtCompile: true," "\n"
" }," "\n"
"" "\n"
" c2: {" "\n"
" // control inlining of method" "\n"
" // + force inline, - dont inline" "\n"
" inline : \"+java/util.*\"," "\n"
" PrintInlining: true," "\n"
" }," "\n"
"" "\n"
" // directives outside a specific preset applies to all compilers" "\n"
" inline : [ \"+java/util.*\", \"-com/sun.*\"]," "\n"
" BreakAtExecute: true," "\n"
" Log: true," "\n"
" }," "\n"
" {" "\n"
" // matching several patterns require an array" "\n"
" match: [\"baz.*\",\"frob.*\"]," "\n"
"" "\n"
" // applies to all compilers" "\n"
" // + force inline, - dont inline" "\n"
" inline : [ \"+java/util.*\", \"-com/sun.*\" ]," "\n"
" PrintInlining: true," "\n"
"" "\n"
" // force matching compiles to be blocking/syncronous" "\n"
" PrintNMethods: true" "\n"
" }," "\n"
"]" "\n", true);
// Test max stack depth
DirectivesParser::test(
"[" "\n" // depth 1: type_dir_array
" {" "\n" // depth 2: type_directives
" match: \"*.*\"," // match required
" c1:" "\n" // depth 3: type_c1
" {" "\n"
" inline:" "\n" // depth 4: type_inline
" [" "\n" // depth 5: type_value_array
" \"foo\"," "\n"
" \"bar\"," "\n"
" ]" "\n" // depth 3: pop type_value_array and type_inline keys
" }" "\n" // depth 2: pop type_c1 key
" }" "\n" // depth 1: pop type_directives key
"]" "\n", true); // depth 0: pop type_dir_array key
// Test max stack depth
DirectivesParser::test(
"[{c1:{c1:{c1:{c1:{c1:{c1:{c1:{}}}}}}}}]", false);
DirectivesParser::test(
"[" "\n"
" {" "\n"
" c1: true," "\n"
" c2: true," "\n"
" match: true," "\n"
" inline: true," "\n"
" enable: true," "\n"
" c1: {" "\n"
" preset: true," "\n"
" }" "\n"
" }" "\n"
"]" "\n", false);
return true;
}
#endif

View file

@ -0,0 +1,141 @@
/*
* 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.
*
*/
#ifndef SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
#define SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
#include "utilities/json.hpp"
#include "compiler/compilerDirectives.hpp"
enum FlagType {
boolFlag,
intxFlag,
doubleFlag,
ccstrFlag,
ccstrlistFlag,
UnknownFlagType
};
static const char* flag_type_names[] = {
"bool",
"int",
"double",
"string",
"string list",
"unknown"
};
class DirectivesParser : public JSON {
public:
static bool has_file();
static bool parse_from_flag();
static bool parse_from_file(const char* filename, outputStream* st);
static bool parse_string(const char* string, outputStream* st);
bool install_directives();
private:
DirectivesParser(const char* text, outputStream* st);
~DirectivesParser();
bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
static bool parse_from_file_inner(const char* filename, outputStream* st);
// types of "keys". i.e recognized <key>:<value> pairs in our JSON syntax
typedef enum {
type_c1,
type_c2,
type_enable,
type_preset,
type_match,
type_inline,
// After here, there is no correlation between
// keytype and keys array
//type_strategy,
type_flag,
//type_dir,
// Synthetic.
type_dir_array,
type_directives,
type_value_array
} keytype;
// name, type, dtd info and maybe a setter
// this is how we map key-values
typedef struct {
const char *name;
keytype type;
uint allow_array_value : 1;
uint allowedmask;
void (DirectiveSet::*set)(void* arg);
FlagType flag_type;
} key;
// Array with valid keys for the directive file
static const key keys[];
// Marker for outermost moosewings/array
static const key dir_array_key;
// Marker for a directives set (these are "implicit" objects, as in not named)
static const key dir_key;
// Marker for a multi value
static const key value_array_key;
// A compiler directive shouldn't be able to use more than 5 stack slots.
// Example of max stack usage:
// depth 1: type_dir_array [
// depth 2: type_directives {
// depth 3: type_c1 c1: {
// depth 4: type_inline inline:
// depth 5: type_value_array [ ...
static const uint MAX_DEPTH = 5;
const key* stack[MAX_DEPTH];
uint depth;
bool push_key(const char* str, size_t len);
bool push_key(const key* k);
const key* current_key();
const key* pop_key();
static const key* lookup_key(const char* s, size_t len);
bool set_option(JSON_TYPE t, JSON_VAL* v);
bool set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set);
CompilerDirectives* current_directive;
DirectiveSet* current_directiveset;
void push_tmp(CompilerDirectives* dir);
CompilerDirectives* pop_tmp();
CompilerDirectives* _tmp_top; // temporary storage for dirs while parsing
static uint mask(keytype kt);
#ifndef PRODUCT
static void test(const char* json, bool valid);
public:
static bool test();
#endif
};
#endif // SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP

View file

@ -320,13 +320,11 @@ bool MethodMatcher::matches(const methodHandle& method) const {
} }
void MethodMatcher::print_symbol(outputStream* st, Symbol* h, Mode mode) { void MethodMatcher::print_symbol(outputStream* st, Symbol* h, Mode mode) {
ResourceMark rm;
if (mode == Suffix || mode == Substring || mode == Any) { if (mode == Suffix || mode == Substring || mode == Any) {
st->print("*"); st->print("*");
} }
if (mode != Any) { if (mode != Any) {
h->print_symbol_on(st); h->print_utf8_on(st);
} }
if (mode == Prefix || mode == Substring) { if (mode == Prefix || mode == Substring) {
st->print("*"); st->print("*");
@ -334,14 +332,117 @@ void MethodMatcher::print_symbol(outputStream* st, Symbol* h, Mode mode) {
} }
void MethodMatcher::print_base(outputStream* st) { void MethodMatcher::print_base(outputStream* st) {
ResourceMark rm;
print_symbol(st, class_name(), _class_mode); print_symbol(st, class_name(), _class_mode);
st->print("."); st->print(".");
print_symbol(st, method_name(), _method_mode); print_symbol(st, method_name(), _method_mode);
if (signature() != NULL) { if (signature() != NULL) {
signature()->print_symbol_on(st); signature()->print_utf8_on(st);
} }
} }
BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_msg) {
assert(error_msg == NULL, "Don't call here with error_msg already set");
BasicMatcher* bm = new BasicMatcher();
MethodMatcher::parse_method_pattern(line, error_msg, bm);
if (error_msg != NULL) {
delete bm;
return NULL;
}
// check for bad trailing characters
int bytes_read = 0;
sscanf(line, "%*[ \t]%n", &bytes_read);
if (line[bytes_read] != '\0') {
error_msg = "Unrecognized trailing text after method pattern";
delete bm;
return NULL;
}
return bm;
}
bool BasicMatcher::match(const methodHandle& method) {
for (BasicMatcher* current = this; current != NULL; current = current->next()) {
if (current->matches(method)) {
return true;
}
}
return false;
}
void InlineMatcher::print(outputStream* st) {
if (_inline_action == InlineMatcher::force_inline) {
st->print("+");
} else {
st->print("-");
}
print_base(st);
}
InlineMatcher* InlineMatcher::parse_method_pattern(char* line, const char*& error_msg) {
assert(error_msg == NULL, "Dont call here with error_msg already set");
InlineMatcher* im = new InlineMatcher();
MethodMatcher::parse_method_pattern(line, error_msg, im);
if (error_msg != NULL) {
delete im;
return NULL;
}
return im;
}
bool InlineMatcher::match(const methodHandle& method, int inline_action) {
for (InlineMatcher* current = this; current != NULL; current = current->next()) {
if (current->matches(method)) {
return (current->_inline_action == inline_action);
}
}
return false;
}
InlineMatcher* InlineMatcher::parse_inline_pattern(char* str, const char*& error_msg) {
// check first token is +/-
InlineType _inline_action;
switch (str[0]) {
case '-':
_inline_action = InlineMatcher::dont_inline;
break;
case '+':
_inline_action = InlineMatcher::force_inline;
break;
default:
error_msg = "Missing leading inline type (+/-)";
return NULL;
}
str++;
int bytes_read = 0;
assert(error_msg== NULL, "error_msg must not be set yet");
InlineMatcher* im = InlineMatcher::parse_method_pattern(str, error_msg);
if (im == NULL) {
assert(error_msg != NULL, "Must have error message");
return NULL;
}
im->set_action(_inline_action);
return im;
}
InlineMatcher* InlineMatcher::clone() {
InlineMatcher* m = new InlineMatcher();
m->_class_mode = _class_mode;
m->_method_mode = _method_mode;
m->_inline_action = _inline_action;
m->_class_name = _class_name;
if(_class_name != NULL) {
_class_name->increment_refcount();
}
m->_method_name = _method_name;
if (_method_name != NULL) {
_method_name->increment_refcount();
}
m->_signature = _signature;
if (_signature != NULL) {
_signature->increment_refcount();
}
return m;
}

View file

@ -81,35 +81,8 @@ public:
_next(next) { _next(next) {
} }
static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg) { static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg);
assert(error_msg == NULL, "Dont call here with error_msg already set"); bool match(const methodHandle& method);
BasicMatcher* bm = new BasicMatcher();
MethodMatcher::parse_method_pattern(line, error_msg, bm);
if (error_msg != NULL) {
delete bm;
return NULL;
}
// check for bad trailing characters
int bytes_read = 0;
sscanf(line, "%*[ \t]%n", &bytes_read);
if (line[bytes_read] != '\0') {
error_msg = "Unrecognized trailing text after method pattern";
delete bm;
return NULL;
}
return bm;
}
bool match(const methodHandle& method) {
for (BasicMatcher* current = this; current != NULL; current = current->next()) {
if (current->matches(method)) {
return true;
}
}
return false;
}
void set_next(BasicMatcher* next) { _next = next; } void set_next(BasicMatcher* next) { _next = next; }
BasicMatcher* next() { return _next; } BasicMatcher* next() { return _next; }
@ -122,5 +95,33 @@ public:
} }
}; };
class InlineMatcher : public MethodMatcher {
public:
enum InlineType {
unknown_inline,
dont_inline,
force_inline
};
private:
InlineType _inline_action;
InlineMatcher * _next;
InlineMatcher() : MethodMatcher(),
_inline_action(unknown_inline), _next(NULL) {
}
public:
static InlineMatcher* parse_method_pattern(char* line, const char*& error_msg);
bool match(const methodHandle& method, int inline_action);
void print(outputStream* st);
void set_next(InlineMatcher* next) { _next = next; }
InlineMatcher* next() { return _next; }
void set_action(InlineType inline_action) { _inline_action = inline_action; }
int inline_action() { return _inline_action; }
static InlineMatcher* parse_inline_pattern(char* line, const char*& error_msg);
InlineMatcher* clone();
};
#endif // SHARE_VM_COMPILER_METHODMATCHER_HPP #endif // SHARE_VM_COMPILER_METHODMATCHER_HPP

View file

@ -145,7 +145,7 @@ void JVMCICompiler::compile_method(methodHandle method, int entry_bci, JVMCIEnv*
// Compilation entry point for methods // Compilation entry point for methods
void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) { void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
ShouldNotReachHere(); ShouldNotReachHere();
} }

View file

@ -69,7 +69,7 @@ public:
void bootstrap(); void bootstrap();
// Compilation entry point for methods // Compilation entry point for methods
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env); void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env);

View file

@ -154,6 +154,10 @@ char* Symbol::as_C_string_flexible_buffer(Thread* t,
return as_C_string(str, buf_len); return as_C_string(str, buf_len);
} }
void Symbol::print_utf8_on(outputStream* st) const {
st->print("%s", as_C_string());
}
void Symbol::print_symbol_on(outputStream* st) const { void Symbol::print_symbol_on(outputStream* st) const {
ResourceMark rm; ResourceMark rm;
st = st ? st : tty; st = st ? st : tty;

View file

@ -225,6 +225,7 @@ class Symbol : public MetaspaceObj {
// Printing // Printing
void print_symbol_on(outputStream* st = NULL) const; void print_symbol_on(outputStream* st = NULL) const;
void print_utf8_on(outputStream* st) const;
void print_on(outputStream* st) const; // First level print void print_on(outputStream* st) const; // First level print
void print_value_on(outputStream* st) const; // Second level print. void print_value_on(outputStream* st) const; // Second level print.

View file

@ -25,6 +25,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "libadt/vectset.hpp" #include "libadt/vectset.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "compiler/compilerDirectives.hpp"
#include "opto/block.hpp" #include "opto/block.hpp"
#include "opto/cfgnode.hpp" #include "opto/cfgnode.hpp"
#include "opto/chaitin.hpp" #include "opto/chaitin.hpp"
@ -365,7 +366,7 @@ PhaseCFG::PhaseCFG(Arena* arena, RootNode* root, Matcher& matcher)
, _node_to_block_mapping(arena) , _node_to_block_mapping(arena)
, _node_latency(NULL) , _node_latency(NULL)
#ifndef PRODUCT #ifndef PRODUCT
, _trace_opto_pipelining(TraceOptoPipelining || C->method_has_option("TraceOptoPipelining")) , _trace_opto_pipelining(C->directive()->TraceOptoPipeliningOption)
#endif #endif
#ifdef ASSERT #ifdef ASSERT
, _raw_oops(arena) , _raw_oops(arena)

View file

@ -368,7 +368,6 @@ public:
class PhaseCFG : public Phase { class PhaseCFG : public Phase {
friend class VMStructs; friend class VMStructs;
private: private:
// Root of whole program // Root of whole program
RootNode* _root; RootNode* _root;

View file

@ -108,7 +108,7 @@ bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method,
int caller_bci, ciCallProfile& profile, int caller_bci, ciCallProfile& profile,
WarmCallInfo* wci_result) { WarmCallInfo* wci_result) {
// Allows targeted inlining // Allows targeted inlining
if (callee_method->should_inline()) { if (C->directive()->should_inline(callee_method)) {
*wci_result = *(WarmCallInfo::always_hot()); *wci_result = *(WarmCallInfo::always_hot());
if (C->print_inlining() && Verbose) { if (C->print_inlining() && Verbose) {
CompileTask::print_inline_indent(inline_level()); CompileTask::print_inline_indent(inline_level());
@ -222,12 +222,12 @@ bool InlineTree::should_not_inline(ciMethod *callee_method,
} }
// ignore heuristic controls on inlining // ignore heuristic controls on inlining
if (callee_method->should_inline()) { if (C->directive()->should_inline(callee_method)) {
set_msg("force inline by CompileCommand"); set_msg("force inline by CompileCommand");
return false; return false;
} }
if (callee_method->should_not_inline()) { if (C->directive()->should_not_inline(callee_method)) {
set_msg("disallowed by CompileCommand"); set_msg("disallowed by CompileCommand");
return true; return true;
} }

View file

@ -154,7 +154,7 @@
notproduct(bool, PrintOptoStatistics, false, \ notproduct(bool, PrintOptoStatistics, false, \
"Print New compiler statistics") \ "Print New compiler statistics") \
\ \
notproduct(bool, PrintOptoAssembly, false, \ diagnostic(bool, PrintOptoAssembly, false, \
"Print New compiler assembly output") \ "Print New compiler assembly output") \
\ \
develop_pd(bool, OptoPeephole, \ develop_pd(bool, OptoPeephole, \
@ -342,6 +342,9 @@
product(bool, SuperWordReductions, true, \ product(bool, SuperWordReductions, true, \
"Enable reductions support in superword.") \ "Enable reductions support in superword.") \
\ \
product(bool, UseCMoveUnconditionally, false, \
"Use CMove (scalar and vector) ignoring profitability test.") \
\
product(bool, DoReserveCopyInSuperWord, true, \ product(bool, DoReserveCopyInSuperWord, true, \
"Create reserve copy of graph in SuperWord.") \ "Create reserve copy of graph in SuperWord.") \
\ \
@ -368,18 +371,18 @@
product(bool, UseRDPCForConstantTableBase, false, \ product(bool, UseRDPCForConstantTableBase, false, \
"Use Sparc RDPC instruction for the constant table base.") \ "Use Sparc RDPC instruction for the constant table base.") \
\ \
develop(bool, PrintIdealGraph, false, \ notproduct(bool, PrintIdealGraph, false, \
"Print ideal graph to XML file / network interface. " \ "Print ideal graph to XML file / network interface. " \
"By default attempts to connect to the visualizer on a socket.") \ "By default attempts to connect to the visualizer on a socket.") \
\ \
develop(intx, PrintIdealGraphLevel, 0, \ notproduct(intx, PrintIdealGraphLevel, 0, \
"Level of detail of the ideal graph printout. " \ "Level of detail of the ideal graph printout. " \
"System-wide value, 0=nothing is printed, 3=all details printed. "\ "System-wide value, 0=nothing is printed, 4=all details printed. "\
"Level of detail of printouts can be set on a per-method level " \ "Level of detail of printouts can be set on a per-method level " \
"as well by using CompileCommand=option.") \ "as well by using CompileCommand=option.") \
range(0, 3) \ range(0, 4) \
\ \
develop(intx, PrintIdealGraphPort, 4444, \ notproduct(intx, PrintIdealGraphPort, 4444, \
"Ideal graph printer to network port") \ "Ideal graph printer to network port") \
range(0, SHRT_MAX) \ range(0, SHRT_MAX) \
\ \
@ -632,7 +635,7 @@
develop(bool, PrintDominators, false, \ develop(bool, PrintDominators, false, \
"Print out dominator trees for GVN") \ "Print out dominator trees for GVN") \
\ \
notproduct(bool, TraceSpilling, false, \ diagnostic(bool, TraceSpilling, false, \
"Trace spilling") \ "Trace spilling") \
\ \
diagnostic(bool, TraceTypeProfile, false, \ diagnostic(bool, TraceTypeProfile, false, \

View file

@ -94,15 +94,16 @@ void C2Compiler::initialize() {
} }
} }
void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) { void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
assert(is_initialized(), "Compiler thread must be initialized"); assert(is_initialized(), "Compiler thread must be initialized");
bool subsume_loads = SubsumeLoads; bool subsume_loads = SubsumeLoads;
bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables(); bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables();
bool eliminate_boxing = EliminateAutoBox; bool eliminate_boxing = EliminateAutoBox;
while (!env->failing()) { while (!env->failing()) {
// Attempt to compile while subsuming loads into machine instructions. // Attempt to compile while subsuming loads into machine instructions.
Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing); Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive);
// Check result and retry if appropriate. // Check result and retry if appropriate.
if (C.failure_reason() != NULL) { if (C.failure_reason() != NULL) {

View file

@ -41,7 +41,8 @@ public:
// Compilation entry point for methods // Compilation entry point for methods
void compile_method(ciEnv* env, void compile_method(ciEnv* env,
ciMethod* target, ciMethod* target,
int entry_bci); int entry_bci,
DirectiveSet* directive);
// sentinel value used to trigger backtracking in compile_method(). // sentinel value used to trigger backtracking in compile_method().
static const char* retry_no_subsuming_loads(); static const char* retry_no_subsuming_loads();

View file

@ -211,7 +211,7 @@ PhaseChaitin::PhaseChaitin(uint unique, PhaseCFG &cfg, Matcher &matcher, bool sc
, _scratch_int_pressure(0, INTPRESSURE) , _scratch_int_pressure(0, INTPRESSURE)
, _scratch_float_pressure(0, FLOATPRESSURE) , _scratch_float_pressure(0, FLOATPRESSURE)
#ifndef PRODUCT #ifndef PRODUCT
, _trace_spilling(TraceSpilling || C->method_has_option("TraceSpilling")) , _trace_spilling(C->directive()->TraceSpillingOption)
#endif #endif
{ {
Compile::TracePhase tp("ctorChaitin", &timers[_t_ctorChaitin]); Compile::TracePhase tp("ctorChaitin", &timers[_t_ctorChaitin]);

View file

@ -64,6 +64,7 @@ macro(CheckCastPP)
macro(ClearArray) macro(ClearArray)
macro(ConstraintCast) macro(ConstraintCast)
macro(CMoveD) macro(CMoveD)
macro(CMoveVD)
macro(CMoveF) macro(CMoveF)
macro(CMoveI) macro(CMoveI)
macro(CMoveL) macro(CMoveL)
@ -161,7 +162,6 @@ macro(LoadN)
macro(LoadRange) macro(LoadRange)
macro(LoadS) macro(LoadS)
macro(Lock) macro(Lock)
macro(LogD)
macro(Log10D) macro(Log10D)
macro(Loop) macro(Loop)
macro(LoopLimit) macro(LoopLimit)

View file

@ -464,7 +464,7 @@ CompileWrapper::CompileWrapper(Compile* compile) : _compile(compile) {
Type::Initialize(compile); Type::Initialize(compile);
_compile->set_scratch_buffer_blob(NULL); _compile->set_scratch_buffer_blob(NULL);
_compile->begin_method(); _compile->begin_method();
_compile->clone_map().set_debug(_compile->has_method() && _compile->method_has_option(_compile->clone_map().debug_option_name)); _compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption);
} }
CompileWrapper::~CompileWrapper() { CompileWrapper::~CompileWrapper() {
_compile->end_method(); _compile->end_method();
@ -496,7 +496,7 @@ void Compile::print_compile_messages() {
tty->print_cr("** Bailout: Recompile without boxing elimination **"); tty->print_cr("** Bailout: Recompile without boxing elimination **");
tty->print_cr("*********************************************************"); tty->print_cr("*********************************************************");
} }
if (env()->break_at_compile()) { if (C->directive()->BreakAtCompileOption) {
// Open the debugger when compiling this method. // Open the debugger when compiling this method.
tty->print("### Breaking when compiling: "); tty->print("### Breaking when compiling: ");
method()->print_short_name(); method()->print_short_name();
@ -617,9 +617,10 @@ debug_only( int Compile::_debug_idx = 100000; )
Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci,
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing ) bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive)
: Phase(Compiler), : Phase(Compiler),
_env(ci_env), _env(ci_env),
_directive(directive),
_log(ci_env->log()), _log(ci_env->log()),
_compile_id(ci_env->compile_id()), _compile_id(ci_env->compile_id()),
_save_argument_registers(false), _save_argument_registers(false),
@ -649,7 +650,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_dead_node_list(comp_arena()), _dead_node_list(comp_arena()),
_dead_node_count(0), _dead_node_count(0),
#ifndef PRODUCT #ifndef PRODUCT
_trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), _trace_opto_output(directive->TraceOptoOutputOption),
_in_dump_cnt(0), _in_dump_cnt(0),
_printer(IdealGraphPrinter::printer()), _printer(IdealGraphPrinter::printer()),
#endif #endif
@ -673,7 +674,11 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_interpreter_frame_size(0), _interpreter_frame_size(0),
_max_node_limit(MaxNodeLimit) { _max_node_limit(MaxNodeLimit) {
C = this; C = this;
#ifndef PRODUCT
if (_printer != NULL) {
_printer->set_compile(this);
}
#endif
CompileWrapper cw(this); CompileWrapper cw(this);
if (CITimeVerbose) { if (CITimeVerbose) {
@ -687,9 +692,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
TraceTime t2(NULL, &_t_methodCompilation, CITime, false); TraceTime t2(NULL, &_t_methodCompilation, CITime, false);
#ifndef PRODUCT #ifndef PRODUCT
bool print_opto_assembly = PrintOptoAssembly || _method->has_option("PrintOptoAssembly"); bool print_opto_assembly = directive->PrintOptoAssemblyOption;
if (!print_opto_assembly) { if (!print_opto_assembly) {
bool print_assembly = (PrintAssembly || _method->should_print_assembly()); bool print_assembly = directive->PrintAssemblyOption;
if (print_assembly && !Disassembler::can_decode()) { if (print_assembly && !Disassembler::can_decode()) {
tty->print_cr("PrintAssembly request changed to PrintOptoAssembly"); tty->print_cr("PrintAssembly request changed to PrintOptoAssembly");
print_opto_assembly = true; print_opto_assembly = true;
@ -698,12 +703,12 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
set_print_assembly(print_opto_assembly); set_print_assembly(print_opto_assembly);
set_parsed_irreducible_loop(false); set_parsed_irreducible_loop(false);
if (method()->has_option("ReplayInline")) { if (directive->ReplayInlineOption) {
_replay_inline_data = ciReplay::load_inline_data(method(), entry_bci(), ci_env->comp_level()); _replay_inline_data = ciReplay::load_inline_data(method(), entry_bci(), ci_env->comp_level());
} }
#endif #endif
set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining)); set_print_inlining(directive->PrintInliningOption NOT_PRODUCT( || PrintOptoInlining));
set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics")); set_print_intrinsics(directive->PrintIntrinsicsOption);
set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it
if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) { if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
@ -837,8 +842,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
// Drain the list. // Drain the list.
Finish_Warm(); Finish_Warm();
#ifndef PRODUCT #ifndef PRODUCT
if (_printer && _printer->should_print(_method)) { if (_printer && _printer->should_print(1)) {
_printer->print_inlining(this); _printer->print_inlining();
} }
#endif #endif
@ -871,10 +876,10 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
NOT_PRODUCT( verify_barriers(); ) NOT_PRODUCT( verify_barriers(); )
// Dump compilation data to replay it. // Dump compilation data to replay it.
if (method()->has_option("DumpReplay")) { if (directive->DumpReplayOption) {
env()->dump_replay_data(_compile_id); env()->dump_replay_data(_compile_id);
} }
if (method()->has_option("DumpInline") && (ilt() != NULL)) { if (directive->DumpInlineOption && (ilt() != NULL)) {
env()->dump_inline_data(_compile_id); env()->dump_inline_data(_compile_id);
} }
@ -918,9 +923,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
frame_size_in_words(), _oop_map_set, frame_size_in_words(), _oop_map_set,
&_handler_table, &_inc_table, &_handler_table, &_inc_table,
compiler, compiler,
env()->comp_level(),
has_unsafe_access(), has_unsafe_access(),
SharedRuntime::is_wide_vector(max_vector_size()), SharedRuntime::is_wide_vector(max_vector_size()),
_directive,
rtm_state() rtm_state()
); );
@ -938,9 +943,11 @@ Compile::Compile( ciEnv* ci_env,
int is_fancy_jump, int is_fancy_jump,
bool pass_tls, bool pass_tls,
bool save_arg_registers, bool save_arg_registers,
bool return_pc ) bool return_pc,
DirectiveSet* directive)
: Phase(Compiler), : Phase(Compiler),
_env(ci_env), _env(ci_env),
_directive(directive),
_log(ci_env->log()), _log(ci_env->log()),
_compile_id(0), _compile_id(0),
_save_argument_registers(save_arg_registers), _save_argument_registers(save_arg_registers),
@ -1090,7 +1097,7 @@ void Compile::Init(int aliaslevel) {
Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist)); Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
set_decompile_count(0); set_decompile_count(0);
set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency")); set_do_freq_based_layout(_directive->BlockLayoutByFrequencyOption);
set_num_loop_opts(LoopOptsCount); set_num_loop_opts(LoopOptsCount);
set_do_inlining(Inline); set_do_inlining(Inline);
set_max_inline_size(MaxInlineSize); set_max_inline_size(MaxInlineSize);
@ -1101,24 +1108,22 @@ void Compile::Init(int aliaslevel) {
set_do_vector_loop(false); set_do_vector_loop(false);
bool do_vector = false;
if (AllowVectorizeOnDemand) { if (AllowVectorizeOnDemand) {
if (has_method() && (method()->has_option("Vectorize") || method()->has_option("VectorizeDebug"))) { if (has_method() && (_directive->VectorizeOption || _directive->VectorizeDebugOption)) {
set_do_vector_loop(true); set_do_vector_loop(true);
NOT_PRODUCT(if (do_vector_loop() && Verbose) {tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n", method()->name()->as_quoted_ascii());})
} else if (has_method() && method()->name() != 0 && } else if (has_method() && method()->name() != 0 &&
method()->intrinsic_id() == vmIntrinsics::_forEachRemaining) { method()->intrinsic_id() == vmIntrinsics::_forEachRemaining) {
set_do_vector_loop(true); set_do_vector_loop(true);
} }
#ifndef PRODUCT
if (do_vector_loop() && Verbose) {
tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n", method()->name()->as_quoted_ascii());
}
#endif
} }
set_use_cmove(UseCMoveUnconditionally /* || do_vector_loop()*/); //TODO: consider do_vector_loop() mandate use_cmove unconditionally
NOT_PRODUCT(if (use_cmove() && Verbose && has_method()) {tty->print("Compile::Init: use CMove without profitability tests for method %s\n", method()->name()->as_quoted_ascii());})
set_age_code(has_method() && method()->profile_aging()); set_age_code(has_method() && method()->profile_aging());
set_rtm_state(NoRTM); // No RTM lock eliding by default set_rtm_state(NoRTM); // No RTM lock eliding by default
method_has_option_value("MaxNodeLimit", _max_node_limit); _max_node_limit = _directive->MaxNodeLimitOption;
#if INCLUDE_RTM_OPT #if INCLUDE_RTM_OPT
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) { if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
int rtm_state = method()->method_data()->rtm_state(); int rtm_state = method()->method_data()->rtm_state();
@ -2091,7 +2096,7 @@ void Compile::Optimize() {
TracePhase tp("optimizer", &timers[_t_optimizer]); TracePhase tp("optimizer", &timers[_t_optimizer]);
#ifndef PRODUCT #ifndef PRODUCT
if (env()->break_at_compile()) { if (_directive->BreakAtCompileOption) {
BREAKPOINT; BREAKPOINT;
} }
@ -4357,7 +4362,6 @@ bool Compile::randomized_select(int count) {
return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count); return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
} }
const char* CloneMap::debug_option_name = "CloneMapDebug";
CloneMap& Compile::clone_map() { return _clone_map; } CloneMap& Compile::clone_map() { return _clone_map; }
void Compile::set_clone_map(Dict* d) { _clone_map._dict = d; } void Compile::set_clone_map(Dict* d) { _clone_map._dict = d; }

View file

@ -374,6 +374,7 @@ class Compile : public Phase {
bool _do_count_invocations; // True if we generate code to count invocations bool _do_count_invocations; // True if we generate code to count invocations
bool _do_method_data_update; // True if we generate code to update MethodData*s bool _do_method_data_update; // True if we generate code to update MethodData*s
bool _do_vector_loop; // True if allowed to execute loop in parallel iterations bool _do_vector_loop; // True if allowed to execute loop in parallel iterations
bool _use_cmove; // True if CMove should be used without profitability analysis
bool _age_code; // True if we need to profile code age (decrement the aging counter) bool _age_code; // True if we need to profile code age (decrement the aging counter)
int _AliasLevel; // Locally-adjusted version of AliasLevel flag. int _AliasLevel; // Locally-adjusted version of AliasLevel flag.
bool _print_assembly; // True if we should dump assembly code for this compilation bool _print_assembly; // True if we should dump assembly code for this compilation
@ -391,6 +392,7 @@ class Compile : public Phase {
// Compilation environment. // Compilation environment.
Arena _comp_arena; // Arena with lifetime equivalent to Compile Arena _comp_arena; // Arena with lifetime equivalent to Compile
ciEnv* _env; // CI interface ciEnv* _env; // CI interface
DirectiveSet* _directive; // Compiler directive
CompileLog* _log; // from CompilerThread CompileLog* _log; // from CompilerThread
const char* _failure_reason; // for record_failure/failing pattern const char* _failure_reason; // for record_failure/failing pattern
GrowableArray<CallGenerator*>* _intrinsics; // List of intrinsics. GrowableArray<CallGenerator*>* _intrinsics; // List of intrinsics.
@ -527,6 +529,10 @@ class Compile : public Phase {
print_inlining_stream()->print("%s", ss.as_string()); print_inlining_stream()->print("%s", ss.as_string());
} }
#ifndef PRODUCT
IdealGraphPrinter* printer() { return _printer; }
#endif
void log_late_inline(CallGenerator* cg); void log_late_inline(CallGenerator* cg);
void log_inline_id(CallGenerator* cg); void log_inline_id(CallGenerator* cg);
void log_inline_failure(const char* msg); void log_inline_failure(const char* msg);
@ -578,6 +584,7 @@ class Compile : public Phase {
// ID for this compilation. Useful for setting breakpoints in the debugger. // ID for this compilation. Useful for setting breakpoints in the debugger.
int compile_id() const { return _compile_id; } int compile_id() const { return _compile_id; }
DirectiveSet* directive() const { return _directive; }
// Does this compilation allow instructions to subsume loads? User // Does this compilation allow instructions to subsume loads? User
// instructions that subsume a load may result in an unschedulable // instructions that subsume a load may result in an unschedulable
@ -651,6 +658,8 @@ class Compile : public Phase {
void set_do_method_data_update(bool z) { _do_method_data_update = z; } void set_do_method_data_update(bool z) { _do_method_data_update = z; }
bool do_vector_loop() const { return _do_vector_loop; } bool do_vector_loop() const { return _do_vector_loop; }
void set_do_vector_loop(bool z) { _do_vector_loop = z; } void set_do_vector_loop(bool z) { _do_vector_loop = z; }
bool use_cmove() const { return _use_cmove; }
void set_use_cmove(bool z) { _use_cmove = z; }
bool age_code() const { return _age_code; } bool age_code() const { return _age_code; }
void set_age_code(bool z) { _age_code = z; } void set_age_code(bool z) { _age_code = z; }
int AliasLevel() const { return _AliasLevel; } int AliasLevel() const { return _AliasLevel; }
@ -671,10 +680,7 @@ class Compile : public Phase {
bool method_has_option(const char * option) { bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option); return method() != NULL && method()->has_option(option);
} }
template<typename T>
bool method_has_option_value(const char * option, T& value) {
return method() != NULL && method()->has_option_value(option, value);
}
#ifndef PRODUCT #ifndef PRODUCT
bool trace_opto_output() const { return _trace_opto_output; } bool trace_opto_output() const { return _trace_opto_output; }
bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; } bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
@ -692,8 +698,8 @@ class Compile : public Phase {
void begin_method() { void begin_method() {
#ifndef PRODUCT #ifndef PRODUCT
if (_printer && _printer->should_print(_method)) { if (_printer && _printer->should_print(1)) {
_printer->begin_method(this); _printer->begin_method();
} }
#endif #endif
C->_latest_stage_start_counter.stamp(); C->_latest_stage_start_counter.stamp();
@ -711,8 +717,8 @@ class Compile : public Phase {
#ifndef PRODUCT #ifndef PRODUCT
if (_printer && _printer->should_print(_method)) { if (_printer && _printer->should_print(level)) {
_printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level); _printer->print_method(CompilerPhaseTypeHelper::to_string(cpt), level);
} }
#endif #endif
C->_latest_stage_start_counter.stamp(); C->_latest_stage_start_counter.stamp();
@ -728,7 +734,7 @@ class Compile : public Phase {
event.commit(); event.commit();
} }
#ifndef PRODUCT #ifndef PRODUCT
if (_printer && _printer->should_print(_method)) { if (_printer && _printer->should_print(level)) {
_printer->end_method(); _printer->end_method();
} }
#endif #endif
@ -1107,7 +1113,7 @@ class Compile : public Phase {
// continuation. // continuation.
Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target,
int entry_bci, bool subsume_loads, bool do_escape_analysis, int entry_bci, bool subsume_loads, bool do_escape_analysis,
bool eliminate_boxing); bool eliminate_boxing, DirectiveSet* directive);
// Second major entry point. From the TypeFunc signature, generate code // Second major entry point. From the TypeFunc signature, generate code
// to pass arguments from the Java calling convention to the C calling // to pass arguments from the Java calling convention to the C calling
@ -1115,7 +1121,7 @@ class Compile : public Phase {
Compile(ciEnv* ci_env, const TypeFunc *(*gen)(), Compile(ciEnv* ci_env, const TypeFunc *(*gen)(),
address stub_function, const char *stub_name, address stub_function, const char *stub_name,
int is_fancy_jump, bool pass_tls, int is_fancy_jump, bool pass_tls,
bool save_arg_registers, bool return_pc); bool save_arg_registers, bool return_pc, DirectiveSet* directive);
// From the TypeFunc signature, generate code to pass arguments // From the TypeFunc signature, generate code to pass arguments
// from Compiled calling convention to Interpreter's calling convention // from Compiled calling convention to Interpreter's calling convention

View file

@ -292,11 +292,11 @@ void IdealGraphPrinter::print_inline_tree(InlineTree *tree) {
} }
void IdealGraphPrinter::print_inlining(Compile* compile) { void IdealGraphPrinter::print_inlining() {
// Print inline tree // Print inline tree
if (_should_send_method) { if (_should_send_method) {
InlineTree *inlineTree = compile->ilt(); InlineTree *inlineTree = C->ilt();
if (inlineTree != NULL) { if (inlineTree != NULL) {
print_inline_tree(inlineTree); print_inline_tree(inlineTree);
} else { } else {
@ -306,9 +306,9 @@ void IdealGraphPrinter::print_inlining(Compile* compile) {
} }
// Has to be called whenever a method is compiled // Has to be called whenever a method is compiled
void IdealGraphPrinter::begin_method(Compile* compile) { void IdealGraphPrinter::begin_method() {
ciMethod *method = compile->method(); ciMethod *method = C->method();
assert(_output, "output stream must exist!"); assert(_output, "output stream must exist!");
assert(method, "null methods are not allowed!"); assert(method, "null methods are not allowed!");
assert(!_current_method, "current method must be null!"); assert(!_current_method, "current method must be null!");
@ -662,16 +662,14 @@ void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set)
} }
} }
void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { void IdealGraphPrinter::print_method(const char *name, int level, bool clear_nodes) {
print(compile, name, (Node *)compile->root(), level, clear_nodes); print(name, (Node *)C->root(), level, clear_nodes);
} }
// Print current ideal graph // Print current ideal graph
void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { void IdealGraphPrinter::print(const char *name, Node *node, int level, bool clear_nodes) {
if (!_current_method || !_should_send_method || !should_print(_current_method, level)) return; if (!_current_method || !_should_send_method || !should_print(level)) return;
this->C = compile;
// Warning, unsafe cast? // Warning, unsafe cast?
_chaitin = (PhaseChaitin *)C->regalloc(); _chaitin = (PhaseChaitin *)C->regalloc();
@ -722,10 +720,8 @@ void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, in
} }
// Should method be printed? // Should method be printed?
bool IdealGraphPrinter::should_print(ciMethod* method, int level) { bool IdealGraphPrinter::should_print(int level) {
intx ideal_graph_level = PrintIdealGraphLevel; return C->directive()->IGVPrintLevelOption >= level;
method->has_option_value("PrintIdealGraphLevel", ideal_graph_level); // update value with per-method value (if available)
return ideal_graph_level >= level;
} }
extern const char *NodeClassNames[]; extern const char *NodeClassNames[];

View file

@ -127,13 +127,14 @@ class IdealGraphPrinter : public CHeapObj<mtCompiler> {
bool traverse_outs(); bool traverse_outs();
void set_traverse_outs(bool b); void set_traverse_outs(bool b);
void print_inlining(Compile* compile); void print_inlining();
void begin_method(Compile* compile); void begin_method();
void end_method(); void end_method();
void print_method(Compile* compile, const char *name, int level=1, bool clear_nodes = false); void print_method(const char *name, int level=1, bool clear_nodes = false);
void print(Compile* compile, const char *name, Node *root, int level=1, bool clear_nodes = false); void print(const char *name, Node *root, int level=1, bool clear_nodes = false);
void print_xml(const char *name); void print_xml(const char *name);
static bool should_print(ciMethod* method, int level = 1); bool should_print(int level);
void set_compile(Compile* compile) {C = compile; }
}; };
#endif #endif

View file

@ -326,9 +326,10 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
// methods access VM-internal data. // methods access VM-internal data.
VM_ENTRY_MARK; VM_ENTRY_MARK;
methodHandle mh(THREAD, m->get_Method()); methodHandle mh(THREAD, m->get_Method());
methodHandle ct(THREAD, method()->get_Method());
is_available = compiler->is_intrinsic_supported(mh, is_virtual) && is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
!vmIntrinsics::is_disabled_by_flags(mh, ct); !C->directive()->is_intrinsic_disabled(mh) &&
!vmIntrinsics::is_disabled_by_flags(mh);
} }
if (is_available) { if (is_available) {
@ -1368,7 +1369,6 @@ bool LibraryCallKit::inline_math(vmIntrinsics::ID id) {
switch (id) { switch (id) {
case vmIntrinsics::_dabs: n = new AbsDNode( arg); break; case vmIntrinsics::_dabs: n = new AbsDNode( arg); break;
case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break; case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break;
case vmIntrinsics::_dlog: n = new LogDNode(C, control(), arg); break;
case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg); break; case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg); break;
default: fatal_unexpected_iid(id); break; default: fatal_unexpected_iid(id); break;
} }
@ -1752,7 +1752,9 @@ bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) {
case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) : case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) :
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN"); runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN");
case vmIntrinsics::_dlog: return Matcher::has_match_rule(Op_LogD) ? inline_math(id) : case vmIntrinsics::_dlog:
return StubRoutines::dlog() != NULL ?
runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG"); runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG");
case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) : case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");

View file

@ -1143,7 +1143,7 @@ public:
// dominated in the outer loop by this node chain: // dominated in the outer loop by this node chain:
// intcon(1)->If->IfFalse->reserved_copy. // intcon(1)->If->IfFalse->reserved_copy.
// The original loop is dominated by the the same node chain but IfTrue projection: // The original loop is dominated by the the same node chain but IfTrue projection:
// intcon(1)->If->IfTrue->original_loop. // intcon(0)->If->IfTrue->original_loop.
// //
// In this implementation of CountedLoopReserveKit the ctor includes create_reserve() // In this implementation of CountedLoopReserveKit the ctor includes create_reserve()
// and the dtor, checks _use_new value. // and the dtor, checks _use_new value.

View file

@ -512,8 +512,11 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
PhiNode* phi = out->as_Phi(); PhiNode* phi = out->as_Phi();
BasicType bt = phi->type()->basic_type(); BasicType bt = phi->type()->basic_type();
switch (bt) { switch (bt) {
case T_FLOAT: case T_DOUBLE:
case T_DOUBLE: { if (C->use_cmove()) {
continue; //TODO: maybe we want to add some cost
}
case T_FLOAT: {
cost += Matcher::float_cmove_cost(); // Could be very expensive cost += Matcher::float_cmove_cost(); // Could be very expensive
break; break;
} }
@ -573,7 +576,7 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
} }
} }
} }
} }//for
Node* bol = iff->in(1); Node* bol = iff->in(1);
assert(bol->Opcode() == Op_Bool, ""); assert(bol->Opcode() == Op_Bool, "");
int cmp_op = bol->in(1)->Opcode(); int cmp_op = bol->in(1)->Opcode();
@ -595,7 +598,8 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
} }
// Check for highly predictable branch. No point in CMOV'ing if // Check for highly predictable branch. No point in CMOV'ing if
// we are going to predict accurately all the time. // we are going to predict accurately all the time.
if (iff->_prob < infrequent_prob || if (C->use_cmove() && cmp_op == Op_CmpD) ;//keep going
else if (iff->_prob < infrequent_prob ||
iff->_prob > (1.0f - infrequent_prob)) iff->_prob > (1.0f - infrequent_prob))
return NULL; return NULL;

View file

@ -2316,7 +2316,8 @@ void Matcher::find_shared( Node *n ) {
case Op_CMoveI: case Op_CMoveI:
case Op_CMoveL: case Op_CMoveL:
case Op_CMoveN: case Op_CMoveN:
case Op_CMoveP: { case Op_CMoveP:
case Op_CMoveVD: {
// Restructure into a binary tree for Matching. It's possible that // Restructure into a binary tree for Matching. It's possible that
// we could move this code up next to the graph reshaping for IfNodes // we could move this code up next to the graph reshaping for IfNodes
// or vice-versa, but I do not want to debug this for Ladybird. // or vice-versa, but I do not want to debug this for Ladybird.

View file

@ -28,6 +28,7 @@
#include "code/debugInfo.hpp" #include "code/debugInfo.hpp"
#include "code/debugInfoRec.hpp" #include "code/debugInfoRec.hpp"
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "compiler/compilerDirectives.hpp"
#include "compiler/oopMap.hpp" #include "compiler/oopMap.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "opto/ad.hpp" #include "opto/ad.hpp"
@ -89,9 +90,8 @@ void Compile::Output() {
} }
// Break before main entry point // Break before main entry point
if( (_method && _method->break_at_execute()) if( (_method && C->directive()->BreakAtExecuteOption)
#ifndef PRODUCT #ifndef PRODUCT
||(OptoBreakpoint && is_method_compilation()) ||(OptoBreakpoint && is_method_compilation())
||(OptoBreakpointOSR && is_osr_compilation()) ||(OptoBreakpointOSR && is_osr_compilation())

View file

@ -2378,13 +2378,13 @@ void Parse::do_one_bytecode() {
} }
#ifndef PRODUCT #ifndef PRODUCT
IdealGraphPrinter *printer = IdealGraphPrinter::printer(); IdealGraphPrinter *printer = C->printer();
if (printer && printer->should_print(_method)) { if (printer && printer->should_print(1)) {
char buffer[256]; char buffer[256];
sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc())); sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
bool old = printer->traverse_outs(); bool old = printer->traverse_outs();
printer->set_traverse_outs(true); printer->set_traverse_outs(true);
printer->print_method(C, buffer, 4); printer->print_method(buffer, 4);
printer->set_traverse_outs(old); printer->set_traverse_outs(old);
} }
#endif #endif

View file

@ -160,8 +160,12 @@ address OptoRuntime::generate_stub( ciEnv* env,
bool pass_tls, bool pass_tls,
bool save_argument_registers, bool save_argument_registers,
bool return_pc) { bool return_pc) {
// Matching the default directive, we currently have no method to match.
DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_full_optimization));
ResourceMark rm; ResourceMark rm;
Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc ); Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc, directive);
DirectivesStack::release(directive);
return C.stub_entry_point(); return C.stub_entry_point();
} }

View file

@ -1508,17 +1508,6 @@ const Type *TanDNode::Value( PhaseTransform *phase ) const {
return TypeD::make( StubRoutines::intrinsic_tan( d ) ); return TypeD::make( StubRoutines::intrinsic_tan( d ) );
} }
//=============================================================================
//------------------------------Value------------------------------------------
// Compute log
const Type *LogDNode::Value( PhaseTransform *phase ) const {
const Type *t1 = phase->type( in(1) );
if( t1 == Type::TOP ) return Type::TOP;
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
double d = t1->getd();
return TypeD::make( StubRoutines::intrinsic_log( d ) );
}
//============================================================================= //=============================================================================
//------------------------------Value------------------------------------------ //------------------------------Value------------------------------------------
// Compute log10 // Compute log10

View file

@ -477,20 +477,6 @@ public:
virtual const Type *Value( PhaseTransform *phase ) const; virtual const Type *Value( PhaseTransform *phase ) const;
}; };
//------------------------------LogDNode---------------------------------------
// Log_e of a double
class LogDNode : public Node {
public:
LogDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
init_flags(Flag_is_expensive);
C->add_expensive_node(this);
}
virtual int Opcode() const;
const Type *bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
virtual const Type *Value( PhaseTransform *phase ) const;
};
//------------------------------Log10DNode--------------------------------------- //------------------------------Log10DNode---------------------------------------
// Log_10 of a double // Log_10 of a double
class Log10DNode : public Node { class Log10DNode : public Node {

View file

@ -37,6 +37,7 @@
#include "opto/opaquenode.hpp" #include "opto/opaquenode.hpp"
#include "opto/superword.hpp" #include "opto/superword.hpp"
#include "opto/vectornode.hpp" #include "opto/vectornode.hpp"
#include "opto/movenode.hpp"
// //
// S U P E R W O R D T R A N S F O R M // S U P E R W O R D T R A N S F O R M
@ -55,6 +56,7 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) :
_mem_slice_tail(arena(), 8, 0, NULL), // memory slice tails _mem_slice_tail(arena(), 8, 0, NULL), // memory slice tails
_node_info(arena(), 8, 0, SWNodeInfo::initial), // info needed per node _node_info(arena(), 8, 0, SWNodeInfo::initial), // info needed per node
_clone_map(phase->C->clone_map()), // map of nodes created in cloning _clone_map(phase->C->clone_map()), // map of nodes created in cloning
_cmovev_kit(_arena, this), // map to facilitate CMoveVD creation
_align_to_ref(NULL), // memory reference to align vectors to _align_to_ref(NULL), // memory reference to align vectors to
_disjoint_ptrs(arena(), 8, 0, OrderedPair::initial), // runtime disambiguated pointer pairs _disjoint_ptrs(arena(), 8, 0, OrderedPair::initial), // runtime disambiguated pointer pairs
_dg(_arena), // dependence graph _dg(_arena), // dependence graph
@ -72,6 +74,7 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) :
_num_work_vecs(0), // amount of vector work we have _num_work_vecs(0), // amount of vector work we have
_num_reductions(0), // amount of reduction work we have _num_reductions(0), // amount of reduction work we have
_do_vector_loop(phase->C->do_vector_loop()), // whether to do vectorization/simd style _do_vector_loop(phase->C->do_vector_loop()), // whether to do vectorization/simd style
_do_reserve_copy(DoReserveCopyInSuperWord),
_ii_first(-1), // first loop generation index - only if do_vector_loop() _ii_first(-1), // first loop generation index - only if do_vector_loop()
_ii_last(-1), // last loop generation index - only if do_vector_loop() _ii_last(-1), // last loop generation index - only if do_vector_loop()
_ii_order(arena(), 8, 0, 0) _ii_order(arena(), 8, 0, 0)
@ -79,12 +82,9 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) :
#ifndef PRODUCT #ifndef PRODUCT
_vector_loop_debug = 0; _vector_loop_debug = 0;
if (_phase->C->method() != NULL) { if (_phase->C->method() != NULL) {
_phase->C->method()->has_option_value("VectorizeDebug", _vector_loop_debug); _vector_loop_debug = phase->C->directive()->VectorizeDebugOption;
}
_CountedLoopReserveKit_debug = 0;
if (_phase->C->method() != NULL) {
_phase->C->method()->has_option_value("DoReserveCopyInSuperWordDebug", _CountedLoopReserveKit_debug);
} }
#endif #endif
} }
@ -102,7 +102,18 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) {
if (!cl->is_main_loop() ) return; // skip normal, pre, and post loops if (!cl->is_main_loop() ) return; // skip normal, pre, and post loops
// Check for no control flow in body (other than exit) // Check for no control flow in body (other than exit)
Node *cl_exit = cl->loopexit(); Node *cl_exit = cl->loopexit();
if (cl_exit->in(0) != lpt->_head) return; if (cl_exit->in(0) != lpt->_head) {
#ifndef PRODUCT
if (TraceSuperWord) {
tty->print_cr("SuperWord::transform_loop: loop too complicated, cl_exit->in(0) != lpt->_head");
tty->print("cl_exit %d", cl_exit->_idx); cl_exit->dump();
tty->print("cl_exit->in(0) %d", cl_exit->in(0)->_idx); cl_exit->in(0)->dump();
tty->print("lpt->_head %d", lpt->_head->_idx); lpt->_head->dump();
lpt->dump_head();
}
#endif
return;
}
// Make sure the are no extra control users of the loop backedge // Make sure the are no extra control users of the loop backedge
if (cl->back_control()->outcnt() != 1) { if (cl->back_control()->outcnt() != 1) {
@ -391,6 +402,10 @@ void SuperWord::SLP_extract() {
construct_my_pack_map(); construct_my_pack_map();
if (_do_vector_loop) {
merge_packs_to_cmovd();
}
filter_packs(); filter_packs();
schedule(); schedule();
@ -1071,6 +1086,17 @@ void SuperWord::set_alignment(Node* s1, Node* s2, int align) {
//------------------------------data_size--------------------------- //------------------------------data_size---------------------------
int SuperWord::data_size(Node* s) { int SuperWord::data_size(Node* s) {
Node* use = NULL; //test if the node is a candidate for CMoveVD optimization, then return the size of CMov
if (_do_vector_loop) {
use = _cmovev_kit.is_Bool_candidate(s);
if (use != NULL) {
return data_size(use);
}
use = _cmovev_kit.is_CmpD_candidate(s);
if (use != NULL) {
return data_size(use);
}
}
int bsize = type2aelembytes(velt_basic_type(s)); int bsize = type2aelembytes(velt_basic_type(s));
assert(bsize != 0, "valid size"); assert(bsize != 0, "valid size");
return bsize; return bsize;
@ -1117,6 +1143,7 @@ bool SuperWord::follow_use_defs(Node_List* p) {
if (s1->is_Load()) return false; if (s1->is_Load()) return false;
int align = alignment(s1); int align = alignment(s1);
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: s1 %d, align %d", s1->_idx, align);)
bool changed = false; bool changed = false;
int start = s1->is_Store() ? MemNode::ValueIn : 1; int start = s1->is_Store() ? MemNode::ValueIn : 1;
int end = s1->is_Store() ? MemNode::ValueIn+1 : s1->req(); int end = s1->is_Store() ? MemNode::ValueIn+1 : s1->req();
@ -1131,6 +1158,7 @@ bool SuperWord::follow_use_defs(Node_List* p) {
pair->push(t1); pair->push(t1);
pair->push(t2); pair->push(t2);
_packset.append(pair); _packset.append(pair);
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: set_alignment(%d, %d, %d)", t1->_idx, t2->_idx, align);)
set_alignment(t1, t2, align); set_alignment(t1, t2, align);
changed = true; changed = true;
} }
@ -1152,6 +1180,7 @@ bool SuperWord::follow_def_uses(Node_List* p) {
if (s1->is_Store()) return false; if (s1->is_Store()) return false;
int align = alignment(s1); int align = alignment(s1);
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: s1 %d, align %d", s1->_idx, align);)
int savings = -1; int savings = -1;
int num_s1_uses = 0; int num_s1_uses = 0;
Node* u1 = NULL; Node* u1 = NULL;
@ -1183,6 +1212,7 @@ bool SuperWord::follow_def_uses(Node_List* p) {
pair->push(u1); pair->push(u1);
pair->push(u2); pair->push(u2);
_packset.append(pair); _packset.append(pair);
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: set_alignment(%d, %d, %d)", u1->_idx, u2->_idx, align);)
set_alignment(u1, u2, align); set_alignment(u1, u2, align);
changed = true; changed = true;
} }
@ -1458,6 +1488,196 @@ void SuperWord::filter_packs() {
#endif #endif
} }
//------------------------------merge_packs_to_cmovd---------------------------
// Merge CMoveD into new vector-nodes
// We want to catch this pattern and subsume CmpD and Bool into CMoveD
//
// SubD ConD
// / | /
// / | / /
// / | / /
// / | / /
// / / /
// / / | /
// v / | /
// CmpD | /
// | | /
// v | /
// Bool | /
// \ | /
// \ | /
// \ | /
// \ | /
// \ v /
// CMoveD
//
void SuperWord::merge_packs_to_cmovd() {
for (int i = _packset.length() - 1; i >= 0; i--) {
_cmovev_kit.make_cmovevd_pack(_packset.at(i));
}
#ifndef PRODUCT
if (TraceSuperWord) {
tty->print_cr("\nSuperWord::merge_packs_to_cmovd(): After merge");
print_packset();
tty->cr();
}
#endif
}
Node* CMoveKit::is_Bool_candidate(Node* def) const {
Node* use = NULL;
if (!def->is_Bool() || def->in(0) != NULL || def->outcnt() != 1) {
return NULL;
}
for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
use = def->fast_out(j);
if (!_sw->same_generation(def, use) || !use->is_CMove()) {
return NULL;
}
}
return use;
}
Node* CMoveKit::is_CmpD_candidate(Node* def) const {
Node* use = NULL;
if (!def->is_Cmp() || def->in(0) != NULL || def->outcnt() != 1) {
return NULL;
}
for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
use = def->fast_out(j);
if (!_sw->same_generation(def, use) || (use = is_Bool_candidate(use)) == NULL || !_sw->same_generation(def, use)) {
return NULL;
}
}
return use;
}
Node_List* CMoveKit::make_cmovevd_pack(Node_List* cmovd_pk) {
Node *cmovd = cmovd_pk->at(0);
if (!cmovd->is_CMove()) {
return NULL;
}
if (pack(cmovd) != NULL) { // already in the cmov pack
return NULL;
}
if (cmovd->in(0) != NULL) {
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CMoveD %d has control flow, escaping...", cmovd->_idx); cmovd->dump();})
return NULL;
}
Node* bol = cmovd->as_CMove()->in(CMoveNode::Condition);
if (!bol->is_Bool()
|| bol->outcnt() != 1
|| !_sw->same_generation(bol, cmovd)
|| bol->in(0) != NULL // BoolNode has control flow!!
|| _sw->my_pack(bol) == NULL) {
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: Bool %d does not fit CMoveD %d for building vector, escaping...", bol->_idx, cmovd->_idx); bol->dump();})
return NULL;
}
Node_List* bool_pk = _sw->my_pack(bol);
if (bool_pk->size() != cmovd_pk->size() ) {
return NULL;
}
Node* cmpd = bol->in(1);
if (!cmpd->is_Cmp()
|| cmpd->outcnt() != 1
|| !_sw->same_generation(cmpd, cmovd)
|| cmpd->in(0) != NULL // CmpDNode has control flow!!
|| _sw->my_pack(cmpd) == NULL) {
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CmpD %d does not fit CMoveD %d for building vector, escaping...", cmpd->_idx, cmovd->_idx); cmpd->dump();})
return NULL;
}
Node_List* cmpd_pk = _sw->my_pack(cmpd);
if (cmpd_pk->size() != cmovd_pk->size() ) {
return NULL;
}
if (!test_cmpd_pack(cmpd_pk, cmovd_pk)) {
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: cmpd pack for CmpD %d failed vectorization test", cmpd->_idx); cmpd->dump();})
return NULL;
}
Node_List* new_cmpd_pk = new Node_List();
uint sz = cmovd_pk->size() - 1;
for (uint i = 0; i <= sz; ++i) {
Node* cmov = cmovd_pk->at(i);
Node* bol = bool_pk->at(i);
Node* cmp = cmpd_pk->at(i);
new_cmpd_pk->insert(i, cmov);
map(cmov, new_cmpd_pk);
map(bol, new_cmpd_pk);
map(cmp, new_cmpd_pk);
_sw->set_my_pack(cmov, new_cmpd_pk); // and keep old packs for cmp and bool
}
_sw->_packset.remove(cmovd_pk);
_sw->_packset.remove(bool_pk);
_sw->_packset.remove(cmpd_pk);
_sw->_packset.append(new_cmpd_pk);
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print_cr("CMoveKit::make_cmovevd_pack: added syntactic CMoveD pack"); _sw->print_pack(new_cmpd_pk);})
return new_cmpd_pk;
}
bool CMoveKit::test_cmpd_pack(Node_List* cmpd_pk, Node_List* cmovd_pk) {
Node* cmpd0 = cmpd_pk->at(0);
assert(cmpd0->is_Cmp(), "CMoveKit::test_cmpd_pack: should be CmpDNode");
assert(cmovd_pk->at(0)->is_CMove(), "CMoveKit::test_cmpd_pack: should be CMoveD");
assert(cmpd_pk->size() == cmovd_pk->size(), "CMoveKit::test_cmpd_pack: should be same size");
Node* in1 = cmpd0->in(1);
Node* in2 = cmpd0->in(2);
Node_List* in1_pk = _sw->my_pack(in1);
Node_List* in2_pk = _sw->my_pack(in2);
if (in1_pk != NULL && in1_pk->size() != cmpd_pk->size()
|| in2_pk != NULL && in2_pk->size() != cmpd_pk->size() ) {
return false;
}
// test if "all" in1 are in the same pack or the same node
if (in1_pk == NULL) {
for (uint j = 1; j < cmpd_pk->size(); j++) {
if (cmpd_pk->at(j)->in(1) != in1) {
return false;
}
}//for: in1_pk is not pack but all CmpD nodes in the pack have the same in(1)
}
// test if "all" in2 are in the same pack or the same node
if (in2_pk == NULL) {
for (uint j = 1; j < cmpd_pk->size(); j++) {
if (cmpd_pk->at(j)->in(2) != in2) {
return false;
}
}//for: in2_pk is not pack but all CmpD nodes in the pack have the same in(2)
}
//now check if cmpd_pk may be subsumed in vector built for cmovd_pk
int cmovd_ind1, cmovd_ind2;
if (cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
&& cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
cmovd_ind1 = CMoveNode::IfFalse;
cmovd_ind2 = CMoveNode::IfTrue;
} else if (cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
&& cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
cmovd_ind2 = CMoveNode::IfFalse;
cmovd_ind1 = CMoveNode::IfTrue;
}
else {
return false;
}
for (uint j = 1; j < cmpd_pk->size(); j++) {
if (cmpd_pk->at(j)->in(1) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind1)
|| cmpd_pk->at(j)->in(2) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind2)) {
return false;
}//if
}
NOT_PRODUCT(if(_sw->is_trace_cmov()) { tty->print("CMoveKit::test_cmpd_pack: cmpd pack for 1st CmpD %d is OK for vectorization: ", cmpd0->_idx); cmpd0->dump(); })
return true;
}
//------------------------------implemented--------------------------- //------------------------------implemented---------------------------
// Can code be generated for pack p? // Can code be generated for pack p?
bool SuperWord::implemented(Node_List* p) { bool SuperWord::implemented(Node_List* p) {
@ -1477,22 +1697,32 @@ bool SuperWord::implemented(Node_List* p) {
} else { } else {
retValue = VectorNode::implemented(opc, size, velt_basic_type(p0)); retValue = VectorNode::implemented(opc, size, velt_basic_type(p0));
} }
if (!retValue) {
if (is_cmov_pack(p)) {
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::implemented: found cmpd pack"); print_pack(p);})
return true;
}
}
} }
return retValue; return retValue;
} }
bool SuperWord::is_cmov_pack(Node_List* p) {
return _cmovev_kit.pack(p->at(0)) != NULL;
}
//------------------------------same_inputs-------------------------- //------------------------------same_inputs--------------------------
// For pack p, are all idx operands the same? // For pack p, are all idx operands the same?
static bool same_inputs(Node_List* p, int idx) { bool SuperWord::same_inputs(Node_List* p, int idx) {
Node* p0 = p->at(0); Node* p0 = p->at(0);
uint vlen = p->size(); uint vlen = p->size();
Node* p0_def = p0->in(idx); Node* p0_def = p0->in(idx);
for (uint i = 1; i < vlen; i++) { for (uint i = 1; i < vlen; i++) {
Node* pi = p->at(i); Node* pi = p->at(i);
Node* pi_def = pi->in(idx); Node* pi_def = pi->in(idx);
if (p0_def != pi_def) if (p0_def != pi_def) {
return false; return false;
} }
}
return true; return true;
} }
@ -1509,9 +1739,10 @@ bool SuperWord::profitable(Node_List* p) {
// the same. Later, implement PackNode and allow differing, non-vector inputs // the same. Later, implement PackNode and allow differing, non-vector inputs
// (maybe just the ones from outside the block.) // (maybe just the ones from outside the block.)
for (uint i = start; i < end; i++) { for (uint i = start; i < end; i++) {
if (!is_vector_use(p0, i)) if (!is_vector_use(p0, i)) {
return false; return false;
} }
}
// Check if reductions are connected // Check if reductions are connected
if (p0->is_reduction()) { if (p0->is_reduction()) {
Node* second_in = p0->in(2); Node* second_in = p0->in(2);
@ -1541,6 +1772,9 @@ bool SuperWord::profitable(Node_List* p) {
// just the ones outside the block.) // just the ones outside the block.)
for (uint i = 0; i < p->size(); i++) { for (uint i = 0; i < p->size(); i++) {
Node* def = p->at(i); Node* def = p->at(i);
if (is_cmov_pack_internal_node(p, def)) {
continue;
}
for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) { for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
Node* use = def->fast_out(j); Node* use = def->fast_out(j);
for (uint k = 0; k < use->req(); k++) { for (uint k = 0; k < use->req(); k++) {
@ -1810,14 +2044,14 @@ void SuperWord::output() {
uint max_vlen_in_bytes = 0; uint max_vlen_in_bytes = 0;
uint max_vlen = 0; uint max_vlen = 0;
NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);}) NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
CountedLoopReserveKit make_reversable(_phase, _lpt, DoReserveCopyInSuperWord); CountedLoopReserveKit make_reversable(_phase, _lpt, do_reserve_copy());
NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);}) NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);})
if (DoReserveCopyInSuperWord && !make_reversable.has_reserved()) { if (do_reserve_copy() && !make_reversable.has_reserved()) {
NOT_PRODUCT({tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");}) NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");})
return; return;
} }
@ -1830,6 +2064,7 @@ void SuperWord::output() {
Node* vn = NULL; Node* vn = NULL;
Node* low_adr = p->at(0); Node* low_adr = p->at(0);
Node* first = executed_first(p); Node* first = executed_first(p);
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d executed first, %d executed last in pack", first->_idx, n->_idx); print_pack(p);})
int opc = n->Opcode(); int opc = n->Opcode();
if (n->is_Load()) { if (n->is_Load()) {
Node* ctl = n->in(MemNode::Control); Node* ctl = n->in(MemNode::Control);
@ -1855,13 +2090,21 @@ void SuperWord::output() {
} else if (n->is_Store()) { } else if (n->is_Store()) {
// Promote value to be stored to vector // Promote value to be stored to vector
Node* val = vector_opd(p, MemNode::ValueIn); Node* val = vector_opd(p, MemNode::ValueIn);
if (val == NULL) {
if (do_reserve_copy()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: val should not be NULL, exiting SuperWord");})
return; //and reverse to backup IG
}
ShouldNotReachHere();
}
Node* ctl = n->in(MemNode::Control); Node* ctl = n->in(MemNode::Control);
Node* mem = first->in(MemNode::Memory); Node* mem = first->in(MemNode::Memory);
Node* adr = low_adr->in(MemNode::Address); Node* adr = low_adr->in(MemNode::Address);
const TypePtr* atyp = n->adr_type(); const TypePtr* atyp = n->adr_type();
vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen); vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen);
vlen_in_bytes = vn->as_StoreVector()->memory_size(); vlen_in_bytes = vn->as_StoreVector()->memory_size();
} else if (n->req() == 3) { } else if (n->req() == 3 && !is_cmov_pack(p)) {
// Promote operands to vector // Promote operands to vector
Node* in1 = NULL; Node* in1 = NULL;
bool node_isa_reduction = n->is_reduction(); bool node_isa_reduction = n->is_reduction();
@ -1870,8 +2113,22 @@ void SuperWord::output() {
in1 = low_adr->in(1); in1 = low_adr->in(1);
} else { } else {
in1 = vector_opd(p, 1); in1 = vector_opd(p, 1);
if (in1 == NULL) {
if (do_reserve_copy()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in1 should not be NULL, exiting SuperWord");})
return; //and reverse to backup IG
}
ShouldNotReachHere();
}
} }
Node* in2 = vector_opd(p, 2); Node* in2 = vector_opd(p, 2);
if (in2 == NULL) {
if (do_reserve_copy()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in2 should not be NULL, exiting SuperWord");})
return; //and reverse to backup IG
}
ShouldNotReachHere();
}
if (VectorNode::is_invariant_vector(in1) && (node_isa_reduction == false) && (n->is_Add() || n->is_Mul())) { if (VectorNode::is_invariant_vector(in1) && (node_isa_reduction == false) && (n->is_Add() || n->is_Mul())) {
// Move invariant vector input into second position to avoid register spilling. // Move invariant vector input into second position to avoid register spilling.
Node* tmp = in1; Node* tmp = in1;
@ -1895,10 +2152,71 @@ void SuperWord::output() {
Node* in = vector_opd(p, 1); Node* in = vector_opd(p, 1);
vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n)); vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes(); vlen_in_bytes = vn->as_Vector()->length_in_bytes();
} else { } else if (is_cmov_pack(p)) {
if (!n->is_CMove()) {
continue;
}
// place here CMoveVDNode
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: print before CMove vectorization"); print_loop(false);})
Node* bol = n->in(CMoveNode::Condition);
if (!bol->is_Bool() && bol->Opcode() == Op_ExtractI && bol->req() > 1 ) {
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d is not Bool node, trying its in(1) node %d", bol->_idx, bol->in(1)->_idx); bol->dump(); bol->in(1)->dump();})
bol = bol->in(1); //may be ExtractNode
}
assert(bol->is_Bool(), "should be BoolNode - too late to bail out!");
if (!bol->is_Bool()) {
if (do_reserve_copy()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: expected %d bool node, exiting SuperWord", bol->_idx); bol->dump();})
return; //and reverse to backup IG
}
ShouldNotReachHere(); ShouldNotReachHere();
} }
int cond = (int)bol->as_Bool()->_test._test;
Node* in_cc = _igvn.intcon(cond);
NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created intcon in_cc node %d", in_cc->_idx); in_cc->dump();})
Node* cc = bol->clone();
cc->set_req(1, in_cc);
NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created bool cc node %d", cc->_idx); cc->dump();})
Node* src1 = vector_opd(p, 2); //2=CMoveNode::IfFalse
if (src1 == NULL) {
if (do_reserve_copy()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src1 should not be NULL, exiting SuperWord");})
return; //and reverse to backup IG
}
ShouldNotReachHere();
}
Node* src2 = vector_opd(p, 3); //3=CMoveNode::IfTrue
if (src2 == NULL) {
if (do_reserve_copy()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src2 should not be NULL, exiting SuperWord");})
return; //and reverse to backup IG
}
ShouldNotReachHere();
}
BasicType bt = velt_basic_type(n);
const TypeVect* vt = TypeVect::make(bt, vlen);
vn = new CMoveVDNode(cc, src1, src2, vt);
NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created new CMove node %d: ", vn->_idx); vn->dump();})
} else {
if (do_reserve_copy()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: ShouldNotReachHere, exiting SuperWord");})
return; //and reverse to backup IG
}
ShouldNotReachHere();
}
assert(vn != NULL, "sanity"); assert(vn != NULL, "sanity");
if (vn == NULL) {
if (do_reserve_copy()){
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: got NULL node, cannot proceed, exiting SuperWord");})
return; //and reverse to backup IG
}
ShouldNotReachHere();
}
_igvn.register_new_node_with_optimizer(vn); _igvn.register_new_node_with_optimizer(vn);
_phase->set_ctrl(vn, _phase->get_ctrl(p->at(0))); _phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
for (uint j = 0; j < p->size(); j++) { for (uint j = 0; j < p->size(); j++) {
@ -1918,7 +2236,8 @@ void SuperWord::output() {
} }
#endif #endif
} }
} }//for (int i = 0; i < _block.length(); i++)
C->set_max_vector_size(max_vlen_in_bytes); C->set_max_vector_size(max_vlen_in_bytes);
if (SuperWordLoopUnrollAnalysis) { if (SuperWordLoopUnrollAnalysis) {
@ -1934,10 +2253,10 @@ void SuperWord::output() {
} }
} }
if (DoReserveCopyInSuperWord) { if (do_reserve_copy()) {
make_reversable.use_new(); make_reversable.use_new();
} }
NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);}) NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);})
return; return;
} }
@ -1951,6 +2270,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
if (same_inputs(p, opd_idx)) { if (same_inputs(p, opd_idx)) {
if (opd->is_Vector() || opd->is_LoadVector()) { if (opd->is_Vector() || opd->is_LoadVector()) {
assert(((opd_idx != 2) || !VectorNode::is_shift(p0)), "shift's count can't be vector"); assert(((opd_idx != 2) || !VectorNode::is_shift(p0)), "shift's count can't be vector");
if (opd_idx == 2 && VectorNode::is_shift(p0)) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("shift's count can't be vector");})
return NULL;
}
return opd; // input is matching vector return opd; // input is matching vector
} }
if ((opd_idx == 2) && VectorNode::is_shift(p0)) { if ((opd_idx == 2) && VectorNode::is_shift(p0)) {
@ -1973,6 +2296,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
_phase->set_ctrl(cnt, _phase->get_ctrl(opd)); _phase->set_ctrl(cnt, _phase->get_ctrl(opd));
} }
assert(opd->bottom_type()->isa_int(), "int type only"); assert(opd->bottom_type()->isa_int(), "int type only");
if (!opd->bottom_type()->isa_int()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should be int type only");})
return NULL;
}
// Move non constant shift count into vector register. // Move non constant shift count into vector register.
cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0)); cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0));
} }
@ -1983,6 +2310,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
return cnt; return cnt;
} }
assert(!opd->is_StoreVector(), "such vector is not expected here"); assert(!opd->is_StoreVector(), "such vector is not expected here");
if (opd->is_StoreVector()) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("StoreVector is not expected here");})
return NULL;
}
// Convert scalar input to vector with the same number of elements as // Convert scalar input to vector with the same number of elements as
// p0's vector. Use p0's type because size of operand's container in // p0's vector. Use p0's type because size of operand's container in
// vector should match p0's size regardless operand's size. // vector should match p0's size regardless operand's size.
@ -2009,6 +2340,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
Node* pi = p->at(i); Node* pi = p->at(i);
Node* in = pi->in(opd_idx); Node* in = pi->in(opd_idx);
assert(my_pack(in) == NULL, "Should already have been unpacked"); assert(my_pack(in) == NULL, "Should already have been unpacked");
if (my_pack(in) != NULL) {
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should already have been unpacked");})
return NULL;
}
assert(opd_bt == in->bottom_type()->basic_type(), "all same type"); assert(opd_bt == in->bottom_type()->basic_type(), "all same type");
pk->add_opd(in); pk->add_opd(in);
} }
@ -2040,7 +2375,8 @@ void SuperWord::insert_extracts(Node_List* p) {
for (uint k = 0; k < use->req(); k++) { for (uint k = 0; k < use->req(); k++) {
Node* n = use->in(k); Node* n = use->in(k);
if (def == n) { if (def == n) {
if (!is_vector_use(use, k)) { Node_List* u_pk = my_pack(use);
if ((u_pk == NULL || !is_cmov_pack(u_pk) || use->is_CMove()) && !is_vector_use(use, k)) {
_n_idx_list.push(use, k); _n_idx_list.push(use, k);
} }
} }

View file

@ -29,6 +29,7 @@
#include "opto/phaseX.hpp" #include "opto/phaseX.hpp"
#include "opto/vectornode.hpp" #include "opto/vectornode.hpp"
#include "utilities/growableArray.hpp" #include "utilities/growableArray.hpp"
#include "libadt/dict.hpp"
// //
// S U P E R W O R D T R A N S F O R M // S U P E R W O R D T R A N S F O R M
@ -200,6 +201,24 @@ class SWNodeInfo VALUE_OBJ_CLASS_SPEC {
static const SWNodeInfo initial; static const SWNodeInfo initial;
}; };
class SuperWord;
class CMoveKit {
friend class SuperWord;
private:
SuperWord* _sw;
Dict* _dict;
CMoveKit(Arena* a, SuperWord* sw) : _sw(sw) {_dict = new Dict(cmpkey, hashkey, a);}
void* _2p(Node* key) const { return (void*)(intptr_t)key; } // 2 conversion functions to make gcc happy
Dict* dict() const { return _dict; }
void map(Node* key, Node_List* val) { assert(_dict->operator[](_2p(key)) == NULL, "key existed"); _dict->Insert(_2p(key), (void*)val); }
void unmap(Node* key) { _dict->Delete(_2p(key)); }
Node_List* pack(Node* key) const { return (Node_List*)_dict->operator[](_2p(key)); }
Node* is_Bool_candidate(Node* nd) const; // if it is the right candidate return corresponding CMove* ,
Node* is_CmpD_candidate(Node* nd) const; // otherwise return NULL
Node_List* make_cmovevd_pack(Node_List* cmovd_pk);
bool test_cmpd_pack(Node_List* cmpd_pk, Node_List* cmovd_pk);
};//class CMoveKit
// JVMCI: OrderedPair is moved up to deal with compilation issues on Windows // JVMCI: OrderedPair is moved up to deal with compilation issues on Windows
//------------------------------OrderedPair--------------------------- //------------------------------OrderedPair---------------------------
// Ordered pair of Node*. // Ordered pair of Node*.
@ -229,6 +248,7 @@ class OrderedPair VALUE_OBJ_CLASS_SPEC {
// Transforms scalar operations into packed (superword) operations. // Transforms scalar operations into packed (superword) operations.
class SuperWord : public ResourceObj { class SuperWord : public ResourceObj {
friend class SWPointer; friend class SWPointer;
friend class CMoveKit;
private: private:
PhaseIdealLoop* _phase; PhaseIdealLoop* _phase;
Arena* _arena; Arena* _arena;
@ -248,7 +268,7 @@ class SuperWord : public ResourceObj {
GrowableArray<Node*> _iteration_last; // nodes in the generation that has deps to phi GrowableArray<Node*> _iteration_last; // nodes in the generation that has deps to phi
GrowableArray<SWNodeInfo> _node_info; // Info needed per node GrowableArray<SWNodeInfo> _node_info; // Info needed per node
CloneMap& _clone_map; // map of nodes created in cloning CloneMap& _clone_map; // map of nodes created in cloning
CMoveKit _cmovev_kit; // support for vectorization of CMov
MemNode* _align_to_ref; // Memory reference that pre-loop will align to MemNode* _align_to_ref; // Memory reference that pre-loop will align to
GrowableArray<OrderedPair> _disjoint_ptrs; // runtime disambiguated pointer pairs GrowableArray<OrderedPair> _disjoint_ptrs; // runtime disambiguated pointer pairs
@ -282,8 +302,11 @@ class SuperWord : public ResourceObj {
bool is_trace_mem_slice() { return (_vector_loop_debug & 4) > 0; } bool is_trace_mem_slice() { return (_vector_loop_debug & 4) > 0; }
bool is_trace_loop() { return (_vector_loop_debug & 8) > 0; } bool is_trace_loop() { return (_vector_loop_debug & 8) > 0; }
bool is_trace_adjacent() { return (_vector_loop_debug & 16) > 0; } bool is_trace_adjacent() { return (_vector_loop_debug & 16) > 0; }
bool is_trace_cmov() { return (_vector_loop_debug & 32) > 0; }
bool is_trace_loop_reverse() { return (_vector_loop_debug & 64) > 0; }
#endif #endif
bool do_vector_loop() { return _do_vector_loop; } bool do_vector_loop() { return _do_vector_loop; }
bool do_reserve_copy() { return _do_reserve_copy; }
private: private:
IdealLoopTree* _lpt; // Current loop tree node IdealLoopTree* _lpt; // Current loop tree node
LoopNode* _lp; // Current LoopNode LoopNode* _lp; // Current LoopNode
@ -292,6 +315,7 @@ class SuperWord : public ResourceObj {
bool _race_possible; // In cases where SDMU is true bool _race_possible; // In cases where SDMU is true
bool _early_return; // True if we do not initialize bool _early_return; // True if we do not initialize
bool _do_vector_loop; // whether to do vectorization/simd style bool _do_vector_loop; // whether to do vectorization/simd style
bool _do_reserve_copy; // do reserve copy of the graph(loop) before final modification in output
int _num_work_vecs; // Number of non memory vector operations int _num_work_vecs; // Number of non memory vector operations
int _num_reductions; // Number of reduction expressions applied int _num_reductions; // Number of reduction expressions applied
int _ii_first; // generation with direct deps from mem phi int _ii_first; // generation with direct deps from mem phi
@ -299,7 +323,6 @@ class SuperWord : public ResourceObj {
GrowableArray<int> _ii_order; GrowableArray<int> _ii_order;
#ifndef PRODUCT #ifndef PRODUCT
uintx _vector_loop_debug; // provide more printing in debug mode uintx _vector_loop_debug; // provide more printing in debug mode
uintx _CountedLoopReserveKit_debug; // for debugging CountedLoopReserveKit
#endif #endif
// Accessors // Accessors
@ -362,7 +385,11 @@ class SuperWord : public ResourceObj {
// my_pack // my_pack
Node_List* my_pack(Node* n) { return !in_bb(n) ? NULL : _node_info.adr_at(bb_idx(n))->_my_pack; } Node_List* my_pack(Node* n) { return !in_bb(n) ? NULL : _node_info.adr_at(bb_idx(n))->_my_pack; }
void set_my_pack(Node* n, Node_List* p) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_my_pack = p; } void set_my_pack(Node* n, Node_List* p) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_my_pack = p; }
// is pack good for converting into one vector node replacing 12 nodes of Cmp, Bool, CMov
bool is_cmov_pack(Node_List* p);
bool is_cmov_pack_internal_node(Node_List* p, Node* nd) { return is_cmov_pack(p) && !nd->is_CMove(); }
// For pack p, are all idx operands the same?
bool same_inputs(Node_List* p, int idx);
// CloneMap utilities // CloneMap utilities
bool same_origin_idx(Node* a, Node* b) const; bool same_origin_idx(Node* a, Node* b) const;
bool same_generation(Node* a, Node* b) const; bool same_generation(Node* a, Node* b) const;
@ -439,6 +466,8 @@ class SuperWord : public ResourceObj {
void construct_my_pack_map(); void construct_my_pack_map();
// Remove packs that are not implemented or not profitable. // Remove packs that are not implemented or not profitable.
void filter_packs(); void filter_packs();
// Merge CMoveD into new vector-nodes
void merge_packs_to_cmovd();
// Adjust the memory graph for the packed operations // Adjust the memory graph for the packed operations
void schedule(); void schedule();
// Remove "current" from its current position in the memory graph and insert // Remove "current" from its current position in the memory graph and insert

View file

@ -86,6 +86,9 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case Op_MulD: case Op_MulD:
assert(bt == T_DOUBLE, "must be"); assert(bt == T_DOUBLE, "must be");
return Op_MulVD; return Op_MulVD;
case Op_CMoveD:
assert(bt == T_DOUBLE, "must be");
return Op_CMoveVD;
case Op_DivF: case Op_DivF:
assert(bt == T_FLOAT, "must be"); assert(bt == T_FLOAT, "must be");
return Op_DivVF; return Op_DivVF;
@ -185,7 +188,7 @@ bool VectorNode::implemented(int opc, uint vlen, BasicType bt) {
(vlen > 1) && is_power_of_2(vlen) && (vlen > 1) && is_power_of_2(vlen) &&
Matcher::vector_size_supported(bt, vlen)) { Matcher::vector_size_supported(bt, vlen)) {
int vopc = VectorNode::opcode(opc, bt); int vopc = VectorNode::opcode(opc, bt);
return vopc > 0 && Matcher::match_rule_supported(vopc); return vopc > 0 && Matcher::match_rule_supported(vopc) && (vopc != Op_CMoveD || vlen == 4);
} }
return false; return false;
} }

View file

@ -44,6 +44,13 @@ class VectorNode : public TypeNode {
init_req(2, n2); init_req(2, n2);
} }
VectorNode(Node* n1, Node* n2, Node* n3, const TypeVect* vt) : TypeNode(vt, 4) {
init_class_id(Class_Vector);
init_req(1, n1);
init_req(2, n2);
init_req(3, n3);
}
const TypeVect* vect_type() const { return type()->is_vect(); } const TypeVect* vect_type() const { return type()->is_vect(); }
uint length() const { return vect_type()->length(); } // Vector length uint length() const { return vect_type()->length(); } // Vector length
uint length_in_bytes() const { return vect_type()->length_in_bytes(); } uint length_in_bytes() const { return vect_type()->length_in_bytes(); }
@ -253,6 +260,14 @@ public:
virtual int Opcode() const; virtual int Opcode() const;
}; };
//------------------------------CMoveVDNode--------------------------------------
// Vector multiply double
class CMoveVDNode : public VectorNode {
public:
CMoveVDNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : VectorNode(in1, in2, in3, vt) {}
virtual int Opcode() const;
};
//------------------------------MulReductionVINode-------------------------------------- //------------------------------MulReductionVINode--------------------------------------
// Vector multiply int as a reduction // Vector multiply int as a reduction
class MulReductionVINode : public ReductionNode { class MulReductionVINode : public ReductionNode {

View file

@ -3840,7 +3840,9 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
#include "gc/g1/heapRegionRemSet.hpp" #include "gc/g1/heapRegionRemSet.hpp"
#endif #endif
#include "compiler/directivesParser.hpp"
#include "memory/guardedMemory.hpp" #include "memory/guardedMemory.hpp"
#include "utilities/json.hpp"
#include "utilities/ostream.hpp" #include "utilities/ostream.hpp"
#include "utilities/quickSort.hpp" #include "utilities/quickSort.hpp"
#if INCLUDE_VM_STRUCTS #if INCLUDE_VM_STRUCTS
@ -3907,6 +3909,8 @@ void execute_internal_vm_tests() {
run_unit_test(ObjectMonitor::sanity_checks()); run_unit_test(ObjectMonitor::sanity_checks());
run_unit_test(Test_linked_list()); run_unit_test(Test_linked_list());
run_unit_test(TestChunkedList_test()); run_unit_test(TestChunkedList_test());
run_unit_test(JSONTest::test());
run_unit_test(DirectivesParser::test());
#if INCLUDE_VM_STRUCTS #if INCLUDE_VM_STRUCTS
run_unit_test(VMStructs::test()); run_unit_test(VMStructs::test());
#endif #endif

View file

@ -551,14 +551,20 @@ WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject metho
method_id = reflected_method_to_jmid(thread, env, method); method_id = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE); CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id)); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(method_id));
DirectiveSet* directive;
if (compilation_context != NULL) { if (compilation_context != NULL) {
compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context); compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE); CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id)); methodHandle cch(THREAD, Method::checked_resolve_jmethod_id(compilation_context_id));
return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, cch); directive = DirectivesStack::getMatchingDirective(cch, CompileBroker::compiler((int)compLevel));
} else { } else {
return CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, NULL); // Calling with NULL matches default directive
directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler((int)compLevel));
} }
bool result = CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, directive);
DirectivesStack::release(directive);
return result;
WB_END WB_END
WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
@ -624,6 +630,47 @@ WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobjec
return (mh->queued_for_compilation() || nm != NULL); return (mh->queued_for_compilation() || nm != NULL);
WB_END WB_END
WB_ENTRY(jboolean, WB_ShouldPrintAssembly(JNIEnv* env, jobject o, jobject method))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, CompileBroker::compiler(CompLevel_simple));
bool result = directive->PrintAssemblyOption;
DirectivesStack::release(directive);
return result;
WB_END
WB_ENTRY(jint, WB_MatchesInline(JNIEnv* env, jobject o, jobject method, jstring pattern))
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
ResourceMark rm;
const char* error_msg = NULL;
char* method_str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(pattern));
InlineMatcher* m = InlineMatcher::parse_inline_pattern(method_str, error_msg);
if (m == NULL) {
assert(error_msg != NULL, "Always have an error message");
tty->print_cr("Got error: %s", error_msg);
return -1; // Pattern failed
}
// Pattern works - now check if it matches
int result;
if (m->match(mh, InlineMatcher::force_inline)) {
result = 2; // Force inline match
} else if (m->match(mh, InlineMatcher::dont_inline)) {
result = 1; // Dont inline match
} else {
result = 0; // No match
}
delete m;
return result;
WB_END
WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern)) WB_ENTRY(jint, WB_MatchesMethod(JNIEnv* env, jobject o, jobject method, jstring pattern))
jmethodID jmid = reflected_method_to_jmid(thread, env, method); jmethodID jmid = reflected_method_to_jmid(thread, env, method);
@ -1475,6 +1522,13 @@ static JNINativeMethod methods[] = {
{CC"matchesMethod", {CC"matchesMethod",
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I", CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
(void*)&WB_MatchesMethod}, (void*)&WB_MatchesMethod},
{CC"matchesInline",
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
(void*)&WB_MatchesInline},
{CC"shouldPrintAssembly",
CC"(Ljava/lang/reflect/Executable;)Z",
(void*)&WB_ShouldPrintAssembly},
{CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag}, {CC"isConstantVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
{CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag}, {CC"isLockedVMFlag", CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
{CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag}, {CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},

View file

@ -3658,6 +3658,9 @@ public:
product(ccstr, CompileCommandFile, NULL, \ product(ccstr, CompileCommandFile, NULL, \
"Read compiler commands from this file [.hotspot_compiler]") \ "Read compiler commands from this file [.hotspot_compiler]") \
\ \
diagnostic(ccstr, CompilerDirectivesFile, NULL, \
"Read compiler directives from this file") \
\
product(ccstrlist, CompileCommand, "", \ product(ccstrlist, CompileCommand, "", \
"Prepend to .hotspot_compiler; e.g. log,java/lang/String.<init>") \ "Prepend to .hotspot_compiler; e.g. log,java/lang/String.<init>") \
\ \
@ -4258,7 +4261,13 @@ public:
"(3) no orphan methods exist for class C (i.e., methods for " \ "(3) no orphan methods exist for class C (i.e., methods for " \
"which the VM declares an intrinsic but that are not declared "\ "which the VM declares an intrinsic but that are not declared "\
"in the loaded class C. " \ "in the loaded class C. " \
"Check (3) is available only in debug builds.") "Check (3) is available only in debug builds.") \
\
diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false, \
"Disable backwards compatibility for compile commands.") \
\
diagnostic(bool, PrintCompilerDirectives, false, \
"Print compiler directives on installation.")
/* /*
* Macros for factoring of globals * Macros for factoring of globals

View file

@ -71,7 +71,7 @@ void vmStructs_init();
void vtableStubs_init(); void vtableStubs_init();
void InlineCacheBuffer_init(); void InlineCacheBuffer_init();
void compilerOracle_init(); void compilerOracle_init();
void compileBroker_init(); bool compileBroker_init();
// Initialization after compiler initialization // Initialization after compiler initialization
bool universe_post_init(); // must happen after compiler_init bool universe_post_init(); // must happen after compiler_init
@ -131,7 +131,9 @@ jint init_globals() {
vtableStubs_init(); vtableStubs_init();
InlineCacheBuffer_init(); InlineCacheBuffer_init();
compilerOracle_init(); compilerOracle_init();
compileBroker_init(); if (!compileBroker_init()) {
return JNI_EINVAL;
}
VMRegImpl::set_regName(); VMRegImpl::set_regName();
if (!universe_post_init()) { if (!universe_post_init()) {

View file

@ -90,6 +90,7 @@ Monitor* CompileThread_lock = NULL;
Monitor* Compilation_lock = NULL; Monitor* Compilation_lock = NULL;
Mutex* CompileTaskAlloc_lock = NULL; Mutex* CompileTaskAlloc_lock = NULL;
Mutex* CompileStatistics_lock = NULL; Mutex* CompileStatistics_lock = NULL;
Mutex* DirectivesStack_lock = NULL;
Mutex* MultiArray_lock = NULL; Mutex* MultiArray_lock = NULL;
Monitor* Terminator_lock = NULL; Monitor* Terminator_lock = NULL;
Monitor* BeforeExit_lock = NULL; Monitor* BeforeExit_lock = NULL;
@ -264,6 +265,7 @@ void mutex_init() {
def(CompiledIC_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks VtableStubs_lock, InlineCacheBuffer_lock def(CompiledIC_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks VtableStubs_lock, InlineCacheBuffer_lock
def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true, Monitor::_safepoint_check_always); def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true, Monitor::_safepoint_check_always);
def(CompileStatistics_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); def(CompileStatistics_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always);
def(DirectivesStack_lock , Mutex , special, true, Monitor::_safepoint_check_never);
def(MultiArray_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock def(MultiArray_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock
def(JvmtiThreadState_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController def(JvmtiThreadState_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController

View file

@ -93,6 +93,7 @@ extern Monitor* CompileThread_lock; // a lock held by compile threa
extern Monitor* Compilation_lock; // a lock used to pause compilation extern Monitor* Compilation_lock; // a lock used to pause compilation
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
extern Mutex* DirectivesStack_lock; // a lock held when mutating the dirstack and ref counting directives
extern Mutex* MultiArray_lock; // a lock used to guard allocation of multi-dim arrays extern Mutex* MultiArray_lock; // a lock used to guard allocation of multi-dim arrays
extern Monitor* Terminator_lock; // a lock used to guard termination of the vm extern Monitor* Terminator_lock; // a lock used to guard termination of the vm
extern Monitor* BeforeExit_lock; // a lock used to guard cleanups and shutdown hooks extern Monitor* BeforeExit_lock; // a lock used to guard cleanups and shutdown hooks

View file

@ -2696,6 +2696,12 @@ void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) {
if (nm != NULL) { if (nm != NULL) {
method->set_code(method, nm); method->set_code(method, nm);
DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_simple));
if (directive->PrintAssemblyOption) {
Disassembler::decode(nm, tty);
}
DirectivesStack::release(directive);
} }
} }
} // Unlock AdapterHandlerLibrary_lock } // Unlock AdapterHandlerLibrary_lock

View file

@ -149,8 +149,8 @@ address StubRoutines::_montgomeryMultiply = NULL;
address StubRoutines::_montgomerySquare = NULL; address StubRoutines::_montgomerySquare = NULL;
address StubRoutines::_dexp = NULL; address StubRoutines::_dexp = NULL;
address StubRoutines::_dlog = NULL;
double (* StubRoutines::_intrinsic_log )(double) = NULL;
double (* StubRoutines::_intrinsic_log10 )(double) = NULL; double (* StubRoutines::_intrinsic_log10 )(double) = NULL;
double (* StubRoutines::_intrinsic_pow )(double, double) = NULL; double (* StubRoutines::_intrinsic_pow )(double, double) = NULL;
double (* StubRoutines::_intrinsic_sin )(double) = NULL; double (* StubRoutines::_intrinsic_sin )(double) = NULL;

View file

@ -208,6 +208,7 @@ class StubRoutines: AllStatic {
static address _montgomerySquare; static address _montgomerySquare;
static address _dexp; static address _dexp;
static address _dlog;
// These are versions of the java.lang.Math methods which perform // These are versions of the java.lang.Math methods which perform
// the same operations as the intrinsic version. They are used for // the same operations as the intrinsic version. They are used for
@ -215,7 +216,6 @@ class StubRoutines: AllStatic {
// intrinsic version returns the same result as the strict version // intrinsic version returns the same result as the strict version
// then they can be set to the appropriate function from // then they can be set to the appropriate function from
// SharedRuntime. // SharedRuntime.
static double (*_intrinsic_log)(double);
static double (*_intrinsic_log10)(double); static double (*_intrinsic_log10)(double);
static double (*_intrinsic_pow)(double, double); static double (*_intrinsic_pow)(double, double);
static double (*_intrinsic_sin)(double); static double (*_intrinsic_sin)(double);
@ -377,17 +377,14 @@ class StubRoutines: AllStatic {
static address montgomerySquare() { return _montgomerySquare; } static address montgomerySquare() { return _montgomerySquare; }
static address dexp() { return _dexp; } static address dexp() { return _dexp; }
static address dlog() { return _dlog; }
static address select_fill_function(BasicType t, bool aligned, const char* &name); static address select_fill_function(BasicType t, bool aligned, const char* &name);
static address zero_aligned_words() { return _zero_aligned_words; } static address zero_aligned_words() { return _zero_aligned_words; }
static double intrinsic_log(double d) {
assert(_intrinsic_log != NULL, "must be defined");
return _intrinsic_log(d);
}
static double intrinsic_log10(double d) { static double intrinsic_log10(double d) {
assert(_intrinsic_log != NULL, "must be defined"); assert(_intrinsic_log10 != NULL, "must be defined");
return _intrinsic_log10(d); return _intrinsic_log10(d);
} }
static double intrinsic_pow(double d, double d2) { static double intrinsic_pow(double d, double d2) {

View file

@ -246,12 +246,6 @@
#ifndef REG_COUNT #ifndef REG_COUNT
#define REG_COUNT 0 #define REG_COUNT 0
#endif #endif
// whole purpose of this function is to work around bug c++/27724 in gcc 4.1.1
// with optimization turned on it doesn't affect produced code
static inline uint64_t cast_uint64_t(size_t x)
{
return x;
}
#if INCLUDE_JVMTI #if INCLUDE_JVMTI
#define JVMTI_STRUCTS(static_field) \ #define JVMTI_STRUCTS(static_field) \
@ -869,6 +863,7 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
static_field(StubRoutines, _squareToLen, address) \ static_field(StubRoutines, _squareToLen, address) \
static_field(StubRoutines, _mulAdd, address) \ static_field(StubRoutines, _mulAdd, address) \
static_field(StubRoutines, _dexp, address) \ static_field(StubRoutines, _dexp, address) \
static_field(StubRoutines, _dlog, address) \
static_field(StubRoutines, _jbyte_arraycopy, address) \ static_field(StubRoutines, _jbyte_arraycopy, address) \
static_field(StubRoutines, _jshort_arraycopy, address) \ static_field(StubRoutines, _jshort_arraycopy, address) \
static_field(StubRoutines, _jint_arraycopy, address) \ static_field(StubRoutines, _jint_arraycopy, address) \
@ -2070,7 +2065,6 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
declare_c2_type(TanDNode, Node) \ declare_c2_type(TanDNode, Node) \
declare_c2_type(AtanDNode, Node) \ declare_c2_type(AtanDNode, Node) \
declare_c2_type(SqrtDNode, Node) \ declare_c2_type(SqrtDNode, Node) \
declare_c2_type(LogDNode, Node) \
declare_c2_type(Log10DNode, Node) \ declare_c2_type(Log10DNode, Node) \
declare_c2_type(PowDNode, Node) \ declare_c2_type(PowDNode, Node) \
declare_c2_type(ReverseBytesINode, Node) \ declare_c2_type(ReverseBytesINode, Node) \
@ -2101,6 +2095,7 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
declare_c2_type(MulVFNode, VectorNode) \ declare_c2_type(MulVFNode, VectorNode) \
declare_c2_type(MulReductionVFNode, ReductionNode) \ declare_c2_type(MulReductionVFNode, ReductionNode) \
declare_c2_type(MulVDNode, VectorNode) \ declare_c2_type(MulVDNode, VectorNode) \
declare_c2_type(CMoveVDNode, VectorNode) \
declare_c2_type(MulReductionVDNode, ReductionNode) \ declare_c2_type(MulReductionVDNode, ReductionNode) \
declare_c2_type(DivVFNode, VectorNode) \ declare_c2_type(DivVFNode, VectorNode) \
declare_c2_type(DivVDNode, VectorNode) \ declare_c2_type(DivVDNode, VectorNode) \
@ -2897,7 +2892,7 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
// This macro generates a VMStructEntry line for a nonstatic field // This macro generates a VMStructEntry line for a nonstatic field
#define GENERATE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ #define GENERATE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
{ QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, cast_uint64_t(offset_of(typeName, fieldName)), NULL }, { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 0, offset_of(typeName, fieldName), NULL },
// This macro generates a VMStructEntry line for a static field // This macro generates a VMStructEntry line for a static field
#define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ #define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \
@ -2912,7 +2907,7 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
// nonstatic field, in which the size of the type is also specified. // nonstatic field, in which the size of the type is also specified.
// The type string is given as NULL, indicating an "opaque" type. // The type string is given as NULL, indicating an "opaque" type.
#define GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, size) \ #define GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, size) \
{ QUOTE(typeName), QUOTE(fieldName), NULL, 0, cast_uint64_t(offset_of(typeName, fieldName)), NULL }, { QUOTE(typeName), QUOTE(fieldName), NULL, 0, offset_of(typeName, fieldName), NULL },
// This macro generates a VMStructEntry line for an unchecked // This macro generates a VMStructEntry line for an unchecked
// static field, in which the size of the type is also specified. // static field, in which the size of the type is also specified.
@ -3100,10 +3095,10 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
// //
#define GENERATE_VM_LONG_CONSTANT_ENTRY(name) \ #define GENERATE_VM_LONG_CONSTANT_ENTRY(name) \
{ QUOTE(name), cast_uint64_t(name) }, { QUOTE(name), name },
#define GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) \ #define GENERATE_PREPROCESSOR_VM_LONG_CONSTANT_ENTRY(name, value) \
{ name, cast_uint64_t(value) }, { name, value },
// This macro generates the sentinel value indicating the end of the list // This macro generates the sentinel value indicating the end of the list
#define GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() \ #define GENERATE_VM_LONG_CONSTANT_LAST_ENTRY() \
@ -3555,43 +3550,40 @@ VMStructs::init() {
extern "C" { extern "C" {
// see comments on cast_uint64_t at the top of this file #define STRIDE(array) ((char*)&array[1] - (char*)&array[0])
#define ASSIGN_CONST_TO_64BIT_VAR(var, expr) \
JNIEXPORT uint64_t var = cast_uint64_t(expr);
#define ASSIGN_OFFSET_TO_64BIT_VAR(var, type, field) \
ASSIGN_CONST_TO_64BIT_VAR(var, offset_of(type, field))
#define ASSIGN_STRIDE_TO_64BIT_VAR(var, array) \
ASSIGN_CONST_TO_64BIT_VAR(var, (char*)&array[1] - (char*)&array[0])
JNIEXPORT VMStructEntry* gHotSpotVMStructs = VMStructs::localHotSpotVMStructs; JNIEXPORT VMStructEntry* gHotSpotVMStructs = VMStructs::localHotSpotVMStructs;
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryTypeNameOffset, VMStructEntry, typeName); JNIEXPORT uint64_t gHotSpotVMStructEntryTypeNameOffset = offset_of(VMStructEntry, typeName);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryFieldNameOffset, VMStructEntry, fieldName); JNIEXPORT uint64_t gHotSpotVMStructEntryFieldNameOffset = offset_of(VMStructEntry, fieldName);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryTypeStringOffset, VMStructEntry, typeString); JNIEXPORT uint64_t gHotSpotVMStructEntryTypeStringOffset = offset_of(VMStructEntry, typeString);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryIsStaticOffset, VMStructEntry, isStatic); JNIEXPORT uint64_t gHotSpotVMStructEntryIsStaticOffset = offset_of(VMStructEntry, isStatic);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryOffsetOffset, VMStructEntry, offset); JNIEXPORT uint64_t gHotSpotVMStructEntryOffsetOffset = offset_of(VMStructEntry, offset);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMStructEntryAddressOffset, VMStructEntry, address); JNIEXPORT uint64_t gHotSpotVMStructEntryAddressOffset = offset_of(VMStructEntry, address);
ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMStructEntryArrayStride, gHotSpotVMStructs); JNIEXPORT uint64_t gHotSpotVMStructEntryArrayStride = STRIDE(gHotSpotVMStructs);
JNIEXPORT VMTypeEntry* gHotSpotVMTypes = VMStructs::localHotSpotVMTypes; JNIEXPORT VMTypeEntry* gHotSpotVMTypes = VMStructs::localHotSpotVMTypes;
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryTypeNameOffset, VMTypeEntry, typeName); JNIEXPORT uint64_t gHotSpotVMTypeEntryTypeNameOffset = offset_of(VMTypeEntry, typeName);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntrySuperclassNameOffset, VMTypeEntry, superclassName); JNIEXPORT uint64_t gHotSpotVMTypeEntrySuperclassNameOffset = offset_of(VMTypeEntry, superclassName);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsOopTypeOffset, VMTypeEntry, isOopType); JNIEXPORT uint64_t gHotSpotVMTypeEntryIsOopTypeOffset = offset_of(VMTypeEntry, isOopType);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsIntegerTypeOffset, VMTypeEntry, isIntegerType); JNIEXPORT uint64_t gHotSpotVMTypeEntryIsIntegerTypeOffset = offset_of(VMTypeEntry, isIntegerType);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntryIsUnsignedOffset, VMTypeEntry, isUnsigned); JNIEXPORT uint64_t gHotSpotVMTypeEntryIsUnsignedOffset = offset_of(VMTypeEntry, isUnsigned);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMTypeEntrySizeOffset, VMTypeEntry, size); JNIEXPORT uint64_t gHotSpotVMTypeEntrySizeOffset = offset_of(VMTypeEntry, size);
ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMTypeEntryArrayStride,gHotSpotVMTypes); JNIEXPORT uint64_t gHotSpotVMTypeEntryArrayStride = STRIDE(gHotSpotVMTypes);
JNIEXPORT VMIntConstantEntry* gHotSpotVMIntConstants = VMStructs::localHotSpotVMIntConstants; JNIEXPORT VMIntConstantEntry* gHotSpotVMIntConstants = VMStructs::localHotSpotVMIntConstants;
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMIntConstantEntryNameOffset, VMIntConstantEntry, name); JNIEXPORT uint64_t gHotSpotVMIntConstantEntryNameOffset = offset_of(VMIntConstantEntry, name);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMIntConstantEntryValueOffset, VMIntConstantEntry, value); JNIEXPORT uint64_t gHotSpotVMIntConstantEntryValueOffset = offset_of(VMIntConstantEntry, value);
ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMIntConstantEntryArrayStride, gHotSpotVMIntConstants); JNIEXPORT uint64_t gHotSpotVMIntConstantEntryArrayStride = STRIDE(gHotSpotVMIntConstants);
JNIEXPORT VMLongConstantEntry* gHotSpotVMLongConstants = VMStructs::localHotSpotVMLongConstants; JNIEXPORT VMLongConstantEntry* gHotSpotVMLongConstants = VMStructs::localHotSpotVMLongConstants;
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryNameOffset, VMLongConstantEntry, name); JNIEXPORT uint64_t gHotSpotVMLongConstantEntryNameOffset = offset_of(VMLongConstantEntry, name);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMLongConstantEntryValueOffset, VMLongConstantEntry, value); JNIEXPORT uint64_t gHotSpotVMLongConstantEntryValueOffset = offset_of(VMLongConstantEntry, value);
ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMLongConstantEntryArrayStride, gHotSpotVMLongConstants); JNIEXPORT uint64_t gHotSpotVMLongConstantEntryArrayStride = STRIDE(gHotSpotVMLongConstants);
JNIEXPORT VMAddressEntry* gHotSpotVMAddresses = VMStructs::localHotSpotVMAddresses; JNIEXPORT VMAddressEntry* gHotSpotVMAddresses = VMStructs::localHotSpotVMAddresses;
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryNameOffset, VMAddressEntry, name); JNIEXPORT uint64_t gHotSpotVMAddressEntryNameOffset = offset_of(VMAddressEntry, name);
ASSIGN_OFFSET_TO_64BIT_VAR(gHotSpotVMAddressEntryValueOffset, VMAddressEntry, value); JNIEXPORT uint64_t gHotSpotVMAddressEntryValueOffset = offset_of(VMAddressEntry, value);
ASSIGN_STRIDE_TO_64BIT_VAR(gHotSpotVMAddressEntryArrayStride, gHotSpotVMAddresses); JNIEXPORT uint64_t gHotSpotVMAddressEntryArrayStride = STRIDE(gHotSpotVMAddresses);
} }
#ifdef ASSERT #ifdef ASSERT

View file

@ -28,7 +28,6 @@
#include "code/codeCache.hpp" #include "code/codeCache.hpp"
#include "code/codeCacheExtensions.hpp" #include "code/codeCacheExtensions.hpp"
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "compiler/compilerOracle.hpp"
#include "gc/shared/isGCActiveMark.hpp" #include "gc/shared/isGCActiveMark.hpp"
#include "memory/heapInspection.hpp" #include "memory/heapInspection.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"

Some files were not shown because too many files have changed in this diff Show more