--- old/src/hotspot/cpu/x86/assembler_x86.cpp 2018-10-31 14:22:32.878960472 +0100 +++ new/src/hotspot/cpu/x86/assembler_x86.cpp 2018-10-31 14:22:32.758960568 +0100 @@ -3350,6 +3350,24 @@ emit_int8((unsigned char)(0xD0 | encode)); } +void Assembler::btsl(Address dst, Register idx) { + InstructionMark im(this); + + prefix(dst, idx); + emit_int8(0x0F); + emit_int8(0xAB); + emit_operand(idx, dst); +} + +void Assembler::btrl(Address dst, Register idx) { + InstructionMark im(this); + + prefix(dst, idx); + emit_int8(0x0F); + emit_int8(0xB3); + emit_operand(idx, dst); +} + void Assembler::orl(Address dst, int32_t imm32) { InstructionMark im(this); prefix(dst); --- old/src/hotspot/cpu/x86/assembler_x86.hpp 2018-10-31 14:22:33.207960211 +0100 +++ new/src/hotspot/cpu/x86/assembler_x86.hpp 2018-10-31 14:22:33.087960306 +0100 @@ -1575,6 +1575,9 @@ void notq(Register dst); #endif + void btsl(Address dst, Register idx); + void btrl(Address dst, Register idx); + void orl(Address dst, int32_t imm32); void orl(Register dst, int32_t imm32); void orl(Register dst, Address src); --- old/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp 2018-10-31 14:22:33.499959979 +0100 +++ new/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp 2018-10-31 14:22:33.380960073 +0100 @@ -725,6 +725,36 @@ } +void LIRGenerator::do_BitIntrinsic(Intrinsic* x) { + address routine = NULL; + + if (x->id() == vmIntrinsics::_setBit) + routine = StubRoutines::setBit(); + else if (x->id() == vmIntrinsics::_clrBit) + routine = StubRoutines::clrBit(); + + assert(routine != NULL, "bit intrinsic not available"); + + LIRItem bits(x->argument_at(0), this); + LIRItem index(x->argument_at(1), this); + + bits.load_item(); + LIR_Address* a = new LIR_Address(bits.result(), T_BYTE); + + BasicTypeList signature(2); + signature.append(T_ADDRESS); + signature.append(T_INT); + + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + + LIR_Opr addr = new_pointer_register(); + __ leal(LIR_OprFact::address(a), addr); + __ move(addr, cc->at(0)); + + index.load_item_force(cc->at(1)); + + __ call_runtime_leaf(routine, getThreadTemp(), LIR_OprFact::illegalOpr, cc->args()); +} void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type"); --- old/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp 2018-10-31 14:22:33.789959748 +0100 +++ new/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp 2018-10-31 14:22:33.667959845 +0100 @@ -5265,6 +5265,59 @@ return start; } + address generate_setBit() { + StubCodeMark mark(this, "StubRoutines", "setBit"); + + return generate_bit(true); + } + + address generate_clrBit() { + StubCodeMark mark(this, "StubRoutines", "clrBit"); + + return generate_bit(false); + } + + /** + * Arguments: + * + * Inputs: + * c_rarg0 - byte[] bits + * c_rarg1 - int index + */ + address generate_bit(bool set) { + address start = __ pc(); + + __ enter(); // required for proper stackwalking of RuntimeStub frame + + const Register bits = c_rarg0; + const Register index = c_rarg1; + + Label L_return; + + __ movl(rbx, index); + __ movptr(rdx, bits); + + __ movl(rcx, rbx); + __ shrl(rbx, 3); // hi + __ andl(rcx, 0x7); // lo + + __ null_check(rdx, arrayOopDesc::length_offset_in_bytes()); + __ cmpl(rbx, Address(rdx, arrayOopDesc::length_offset_in_bytes())); + __ jccb(Assembler::aboveEqual, L_return); // TODO throw exception? + + __ lock(); + if (set) + __ btsl(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), rcx); + else + __ btrl(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), rcx); + + __ bind(L_return); + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; + } + address generate_libmExp() { StubCodeMark mark(this, "StubRoutines", "libmExp"); @@ -5736,6 +5789,12 @@ if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dtan)) { StubRoutines::_dtan = generate_libmTan(); } + if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_setBit)) { + StubRoutines::_setBit = generate_setBit(); + } + if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_clrBit)) { + StubRoutines::_clrBit = generate_clrBit(); + } } } --- old/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp 2018-10-31 14:22:34.098959503 +0100 +++ new/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp 2018-10-31 14:22:33.979959597 +0100 @@ -338,6 +338,27 @@ // Various method entries // +address TemplateInterpreterGenerator::generate_bit_entry(AbstractInterpreter::MethodKind kind) { + address entry = __ pc(); + + const Register bits = c_rarg0; + const Register index = c_rarg1; + + __ movptr(bits, Address(rsp, 2 * wordSize)); + __ movl(index, Address(rsp, 1 * wordSize)); + + if (kind == Interpreter::java_lang_System_setBit) + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::setBit()))); + else + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::clrBit()))); + + __ pop(rax); + __ mov(rsp, r13); + __ jmp(rax); + + return entry; +} + address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { // rbx,: Method* --- old/src/hotspot/cpu/x86/x86_64.ad 2018-10-31 14:22:34.392959269 +0100 +++ new/src/hotspot/cpu/x86/x86_64.ad 2018-10-31 14:22:34.260959374 +0100 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -5802,6 +5802,27 @@ %} //----------Store Instructions------------------------------------------------- +// Store Bit +instruct storeZ0(memory mem, rRegI src) +%{ + match(Set mem (StoreZ0 mem src)); + + ins_cost(125); + format %{ "andb $mem, $src\t# byte" %} + opcode(0x20); + ins_encode(lock_prefix, REX_breg_mem(src, mem), OpcP, reg_mem(src, mem)); + ins_pipe(ialu_mem_reg); +%} + +instruct storeZ1(memory mem, rRegI src) +%{ + match(Set mem (StoreZ1 mem src)); + ins_cost(125); + format %{ "orb $mem, $src\t# byte" %} + opcode(0x08); + ins_encode(lock_prefix, REX_breg_mem(src, mem), OpcP, reg_mem(src, mem)); + ins_pipe(ialu_mem_reg); +%} // Store Byte instruct storeB(memory mem, rRegI src) --- old/src/hotspot/share/adlc/forms.cpp 2018-10-31 14:22:34.791958952 +0100 +++ new/src/hotspot/share/adlc/forms.cpp 2018-10-31 14:22:34.668959050 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -271,6 +271,8 @@ } Form::DataType Form::is_store_to_memory(const char *opType) const { + if( strcmp(opType,"StoreZ0")==0) return Form::idealB; + if( strcmp(opType,"StoreZ1")==0) return Form::idealB; if( strcmp(opType,"StoreB")==0) return Form::idealB; if( strcmp(opType,"StoreCM")==0) return Form::idealB; if( strcmp(opType,"StoreC")==0) return Form::idealC; --- old/src/hotspot/share/adlc/formssel.cpp 2018-10-31 14:22:35.078958724 +0100 +++ new/src/hotspot/share/adlc/formssel.cpp 2018-10-31 14:22:34.955958822 +0100 @@ -3485,7 +3485,7 @@ int MatchNode::needs_ideal_memory_edge(FormDict &globals) const { static const char *needs_ideal_memory_list[] = { "StoreI","StoreL","StoreP","StoreN","StoreNKlass","StoreD","StoreF" , - "StoreB","StoreC","Store" ,"StoreFP", + "StoreZ0", "StoreZ1", "StoreB","StoreC","Store" ,"StoreFP", "LoadI", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , "LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load" , "StoreVector", "LoadVector", --- old/src/hotspot/share/c1/c1_Compiler.cpp 2018-10-31 14:22:35.378958485 +0100 +++ new/src/hotspot/share/c1/c1_Compiler.cpp 2018-10-31 14:22:35.259958580 +0100 @@ -156,6 +156,8 @@ case vmIntrinsics::_isInstance: case vmIntrinsics::_isPrimitive: case vmIntrinsics::_currentThread: + case vmIntrinsics::_setBit: + case vmIntrinsics::_clrBit: case vmIntrinsics::_dabs: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsin: --- old/src/hotspot/share/c1/c1_LIRGenerator.cpp 2018-10-31 14:22:35.659958262 +0100 +++ new/src/hotspot/share/c1/c1_LIRGenerator.cpp 2018-10-31 14:22:35.539958357 +0100 @@ -3040,6 +3040,9 @@ case vmIntrinsics::_getClass: do_getClass(x); break; case vmIntrinsics::_currentThread: do_currentThread(x); break; + case vmIntrinsics::_setBit: // fall through + case vmIntrinsics::_clrBit: do_BitIntrinsic(x); break; + case vmIntrinsics::_dlog: // fall through case vmIntrinsics::_dlog10: // fall through case vmIntrinsics::_dabs: // fall through --- old/src/hotspot/share/c1/c1_LIRGenerator.hpp 2018-10-31 14:22:35.957958025 +0100 +++ new/src/hotspot/share/c1/c1_LIRGenerator.hpp 2018-10-31 14:22:35.837958121 +0100 @@ -255,6 +255,7 @@ void do_getClass(Intrinsic* x); void do_currentThread(Intrinsic* x); void do_FmaIntrinsic(Intrinsic* x); + void do_BitIntrinsic(Intrinsic* x); void do_MathIntrinsic(Intrinsic* x); void do_LibmIntrinsic(Intrinsic* x); void do_ArrayCopy(Intrinsic* x); --- old/src/hotspot/share/classfile/vmSymbols.hpp 2018-10-31 14:22:36.241957800 +0100 +++ new/src/hotspot/share/classfile/vmSymbols.hpp 2018-10-31 14:22:36.121957895 +0100 @@ -832,6 +832,12 @@ \ JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \ \ + do_intrinsic(_setBit, java_lang_System, setBit_name, setBit_signature, F_S) \ + do_name( setBit_name, "setBit") \ + do_signature(setBit_signature, "([BI)V") \ + do_intrinsic(_clrBit, java_lang_System, clrBit_name, clrBit_signature, F_S) \ + do_name( clrBit_name, "clrBit") \ + do_signature(clrBit_signature, "([BI)V") \ do_intrinsic(_arraycopy, java_lang_System, arraycopy_name, arraycopy_signature, F_S) \ do_name( arraycopy_name, "arraycopy") \ do_signature(arraycopy_signature, "(Ljava/lang/Object;ILjava/lang/Object;II)V") \ --- old/src/hotspot/share/interpreter/abstractInterpreter.cpp 2018-10-31 14:22:36.539957563 +0100 +++ new/src/hotspot/share/interpreter/abstractInterpreter.cpp 2018-10-31 14:22:36.418957659 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -171,6 +171,8 @@ // TemplateInterpreterGenerator::generate_method_entry() for // for details. switch (m->intrinsic_id()) { + case vmIntrinsics::_setBit: return java_lang_System_setBit; + case vmIntrinsics::_clrBit: return java_lang_System_clrBit; case vmIntrinsics::_dsin : return java_lang_math_sin ; case vmIntrinsics::_dcos : return java_lang_math_cos ; case vmIntrinsics::_dtan : return java_lang_math_tan ; --- old/src/hotspot/share/interpreter/abstractInterpreter.hpp 2018-10-31 14:22:36.822957338 +0100 +++ new/src/hotspot/share/interpreter/abstractInterpreter.hpp 2018-10-31 14:22:36.702957433 +0100 @@ -89,6 +89,8 @@ java_lang_Float_floatToRawIntBits, // implementation of java.lang.Float.floatToRawIntBits() java_lang_Double_longBitsToDouble, // implementation of java.lang.Double.longBitsToDouble() java_lang_Double_doubleToRawLongBits, // implementation of java.lang.Double.doubleToRawLongBits() + java_lang_System_setBit, + java_lang_System_clrBit, number_of_method_entries, invalid = -1 }; @@ -155,6 +157,8 @@ // the compiled version to the intrinsic version. static bool can_be_compiled(const methodHandle& m) { switch (m->intrinsic_id()) { + case vmIntrinsics::_setBit: // fall thru + case vmIntrinsics::_clrBit: // fall thru case vmIntrinsics::_dsin : // fall thru case vmIntrinsics::_dcos : // fall thru case vmIntrinsics::_dtan : // fall thru --- old/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp 2018-10-31 14:22:37.111957108 +0100 +++ new/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp 2018-10-31 14:22:36.991957203 +0100 @@ -228,6 +228,8 @@ method_entry(java_lang_Double_longBitsToDouble); method_entry(java_lang_Double_doubleToRawLongBits); + method_entry(java_lang_System_setBit); + method_entry(java_lang_System_clrBit); #undef method_entry // Bytecodes @@ -411,6 +413,8 @@ address entry_point = NULL; switch (kind) { + case Interpreter::java_lang_System_setBit: // fall thru + case Interpreter::java_lang_System_clrBit: entry_point = generate_bit_entry(kind); break; case Interpreter::zerolocals : break; case Interpreter::zerolocals_synchronized: synchronized = true; break; case Interpreter::native : native = true; break; --- old/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp 2018-10-31 14:22:37.395956882 +0100 +++ new/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp 2018-10-31 14:22:37.275956978 +0100 @@ -90,6 +90,7 @@ address generate_native_entry(bool synchronized); address generate_abstract_entry(void); address generate_math_entry(AbstractInterpreter::MethodKind kind); + address generate_bit_entry(AbstractInterpreter::MethodKind kind); address generate_Reference_get_entry(); address generate_CRC32_update_entry(); address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind); --- old/src/hotspot/share/opto/c2compiler.cpp 2018-10-31 14:22:37.679956657 +0100 +++ new/src/hotspot/share/opto/c2compiler.cpp 2018-10-31 14:22:37.557956754 +0100 @@ -587,6 +587,8 @@ case vmIntrinsics::_vectorizedMismatch: case vmIntrinsics::_ghash_processBlocks: case vmIntrinsics::_base64_encodeBlock: + case vmIntrinsics::_setBit: + case vmIntrinsics::_clrBit: case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: --- old/src/hotspot/share/opto/classes.hpp 2018-10-31 14:22:37.965956429 +0100 +++ new/src/hotspot/share/opto/classes.hpp 2018-10-31 14:22:37.845956525 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,6 +269,8 @@ macro(SqrtF) macro(Start) macro(StartOSR) +macro(StoreZ0) +macro(StoreZ1) macro(StoreB) macro(StoreC) macro(StoreCM) --- old/src/hotspot/share/opto/graphKit.cpp 2018-10-31 14:22:38.251956202 +0100 +++ new/src/hotspot/share/opto/graphKit.cpp 2018-10-31 14:22:38.128956300 +0100 @@ -1515,7 +1515,8 @@ MemNode::MemOrd mo, bool require_atomic_access, bool unaligned, - bool mismatched) { + bool mismatched, + int storeZ) { assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); const TypePtr* adr_type = NULL; debug_only(adr_type = C->get_adr_type(adr_idx)); @@ -1525,6 +1526,10 @@ st = StoreLNode::make_atomic(ctl, mem, adr, adr_type, val, mo); } else if (require_atomic_access && bt == T_DOUBLE) { st = StoreDNode::make_atomic(ctl, mem, adr, adr_type, val, mo); + } else if (bt == T_BYTE && storeZ == 0) { + st = new StoreZ0Node(ctl, mem, adr, adr_type, val, mo); + } else if (bt == T_BYTE && storeZ == 1) { + st = new StoreZ1Node(ctl, mem, adr, adr_type, val, mo); } else { st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); } --- old/src/hotspot/share/opto/graphKit.hpp 2018-10-31 14:22:38.557955959 +0100 +++ new/src/hotspot/share/opto/graphKit.hpp 2018-10-31 14:22:38.437956054 +0100 @@ -553,13 +553,15 @@ MemNode::MemOrd mo, bool require_atomic_access = false, bool unaligned = false, - bool mismatched = false) { + bool mismatched = false, + int storeZ = -1) { // This version computes alias_index from an address type assert(adr_type != NULL, "use other store_to_memory factory"); return store_to_memory(ctl, adr, val, bt, C->get_alias_index(adr_type), mo, require_atomic_access, - unaligned, mismatched); + unaligned, mismatched, + storeZ); } // This is the base version which is given alias index // Return the new StoreXNode @@ -568,7 +570,8 @@ MemNode::MemOrd, bool require_atomic_access = false, bool unaligned = false, - bool mismatched = false); + bool mismatched = false, + int storeZ = -1); // Perform decorated accesses --- old/src/hotspot/share/opto/library_call.cpp 2018-10-31 14:22:38.848955728 +0100 +++ new/src/hotspot/share/opto/library_call.cpp 2018-10-31 14:22:38.724955826 +0100 @@ -308,6 +308,8 @@ Node* get_state_from_sha5_object(Node *sha_object); Node* inline_digestBase_implCompressMB_predicate(int predicate); bool inline_encodeISOArray(); + bool inline_setBit(); + bool inline_clrBit(); bool inline_updateCRC32(); bool inline_updateBytesCRC32(); bool inline_updateByteBufferCRC32(); @@ -841,6 +843,11 @@ case vmIntrinsics::_encodeByteISOArray: return inline_encodeISOArray(); + case vmIntrinsics::_setBit: + return inline_setBit(); + case vmIntrinsics::_clrBit: + return inline_clrBit(); + case vmIntrinsics::_updateCRC32: return inline_updateCRC32(); case vmIntrinsics::_updateBytesCRC32: @@ -5382,6 +5389,39 @@ return true; } +bool LibraryCallKit::inline_setBit() { + Node* bits = argument(0); // type: oop + Node* index = argument(1); // type: int + + Node* hi = _gvn.transform(new RShiftINode(index, intcon(3))); + Node* bit = array_element_address(bits, hi, T_BYTE); + + Node* lo = _gvn.transform(new AndINode(index, intcon(7))); + Node* value = _gvn.transform(new LShiftINode(intcon(1), lo)); + + store_to_memory(control(), bit, value, T_BYTE, TypeAryPtr::BYTES, MemNode::unordered, + false, false, false, 1); + + return true; +} + +bool LibraryCallKit::inline_clrBit() { + Node* bits = argument(0); // type: oop + Node* index = argument(1); // type: int + + Node* hi = _gvn.transform(new RShiftINode(index, intcon(3))); + Node* bit = array_element_address(bits, hi, T_BYTE); + + Node* lo = _gvn.transform(new AndINode(index, intcon(7))); + Node* value = _gvn.transform(new LShiftINode(intcon(1), lo)); + value = _gvn.transform(new XorINode(value, intcon(-1))); + + store_to_memory(control(), bit, value, T_BYTE, TypeAryPtr::BYTES, MemNode::unordered, + false, false, false, 0); + + return true; +} + /** * Calculate CRC32 for byte[] array. * int java.util.zip.CRC32.updateBytes(int crc, byte[] buf, int off, int len) --- old/src/hotspot/share/opto/memnode.hpp 2018-10-31 14:22:39.173955469 +0100 +++ new/src/hotspot/share/opto/memnode.hpp 2018-10-31 14:22:39.053955565 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -622,6 +622,21 @@ virtual BasicType memory_type() const { return T_BYTE; } }; +// Store bit to memory +class StoreZ0Node : public StoreBNode { +public: + StoreZ0Node(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreBNode(c, mem, adr, at, val, mo) {} + virtual int Opcode() const; +}; + +class StoreZ1Node : public StoreBNode { +public: + StoreZ1Node(Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, MemOrd mo) + : StoreBNode(c, mem, adr, at, val, mo) {} + virtual int Opcode() const; +}; + //------------------------------StoreCNode------------------------------------- // Store char/short to memory class StoreCNode : public StoreNode { --- old/src/hotspot/share/runtime/stubRoutines.cpp 2018-10-31 14:22:39.463955239 +0100 +++ new/src/hotspot/share/runtime/stubRoutines.cpp 2018-10-31 14:22:39.344955333 +0100 @@ -152,6 +152,9 @@ address StubRoutines::_vectorizedMismatch = NULL; +address StubRoutines::_setBit = NULL; +address StubRoutines::_clrBit = NULL; + address StubRoutines::_dexp = NULL; address StubRoutines::_dlog = NULL; address StubRoutines::_dlog10 = NULL; --- old/src/hotspot/share/runtime/stubRoutines.hpp 2018-10-31 14:22:39.748955012 +0100 +++ new/src/hotspot/share/runtime/stubRoutines.hpp 2018-10-31 14:22:39.630955106 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -196,6 +196,9 @@ static address _vectorizedMismatch; + static address _setBit; + static address _clrBit; + static address _dexp; static address _dlog; static address _dlog10; @@ -371,6 +374,9 @@ static address vectorizedMismatch() { return _vectorizedMismatch; } + static address setBit() { return _setBit; } + static address clrBit() { return _clrBit; } + static address dexp() { return _dexp; } static address dlog() { return _dlog; } static address dlog10() { return _dlog10; } --- old/src/hotspot/share/runtime/vmStructs.cpp 2018-10-31 14:22:40.041954779 +0100 +++ new/src/hotspot/share/runtime/vmStructs.cpp 2018-10-31 14:22:39.912954882 +0100 @@ -1664,6 +1664,8 @@ declare_c2_type(LoadNKlassNode, LoadNNode) \ declare_c2_type(LoadSNode, LoadNode) \ declare_c2_type(StoreNode, MemNode) \ + declare_c2_type(StoreZ0Node, StoreNode) \ + declare_c2_type(StoreZ1Node, StoreNode) \ declare_c2_type(StoreBNode, StoreNode) \ declare_c2_type(StoreCNode, StoreNode) \ declare_c2_type(StoreINode, StoreNode) \ --- old/src/java.base/share/classes/java/lang/System.java 2018-10-31 14:22:40.355954530 +0100 +++ new/src/java.base/share/classes/java/lang/System.java 2018-10-31 14:22:40.235954625 +0100 @@ -533,6 +533,36 @@ int length); /** + * Set bit atomically + * @param bits bits + * @param index index + */ + @HotSpotIntrinsicCandidate + public static void setBit(byte[] bits, int index) { + throw new UnsupportedOperationException(); + } + + /** + * Clear bit atomically + * @param bits bits + * @param index index + */ + @HotSpotIntrinsicCandidate + public static void clrBit(byte[] bits, int index) { + throw new UnsupportedOperationException(); + } + + /** + * Get bit + * @param bits bits + * @param index index + * @return value + */ + public static boolean isBit(byte[] bits, int index) { + return ((bits[index>>3] >> (index & 7)) & 1) == 1; + } + + /** * Returns the same hash code for the given object as * would be returned by the default method hashCode(), * whether or not the given object's class overrides --- old/src/java.base/share/classes/java/util/RegularEnumSet.java 2018-10-31 14:22:40.657954290 +0100 +++ new/src/java.base/share/classes/java/util/RegularEnumSet.java 2018-10-31 14:22:40.530954391 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,25 +39,50 @@ * Bit vector representation of this set. The 2^k bit indicates the * presence of universe[k] in this set. */ - private long elements = 0L; + private byte[] bits = new byte[8]; + + private void setBits(long elems) { + for (int i=0; i> (i<<3)); + } + + private long elems() { + long elems = 0L; + for (int i=0; i clone() { + RegularEnumSet es = (RegularEnumSet) super.clone(); + es.bits = new byte[8]; + es.setBits(elems()); + return es; + } RegularEnumSet(ClasselementType, Enum[] universe) { super(elementType, universe); } void addRange(E from, E to) { - elements = (-1L >>> (from.ordinal() - to.ordinal() - 1)) << from.ordinal(); + setBits((-1L >>> (from.ordinal() - to.ordinal() - 1)) << from.ordinal()); } void addAll() { if (universe.length != 0) - elements = -1L >>> -universe.length; + setBits(-1L >>> -universe.length); } void complement() { if (universe.length != 0) { - elements = ~elements; - elements &= -1L >>> -universe.length; // Mask unused bits + setBits(~elems() & (-1L >>> -universe.length)); } } @@ -89,7 +114,7 @@ long lastReturned = 0; EnumSetIterator() { - unseen = elements; + unseen = elems(); } public boolean hasNext() { @@ -108,7 +133,7 @@ public void remove() { if (lastReturned == 0) throw new IllegalStateException(); - elements &= ~lastReturned; + setBits(elems() & ~lastReturned); lastReturned = 0; } } @@ -119,7 +144,7 @@ * @return the number of elements in this set */ public int size() { - return Long.bitCount(elements); + return Long.bitCount(elems()); } /** @@ -128,7 +153,7 @@ * @return {@code true} if this set contains no elements */ public boolean isEmpty() { - return elements == 0; + return elems() == 0; } /** @@ -144,7 +169,7 @@ if (eClass != elementType && eClass.getSuperclass() != elementType) return false; - return (elements & (1L << ((Enum)e).ordinal())) != 0; + return System.isBit(bits, ((Enum)e).ordinal()); } // Modification Operations @@ -159,10 +184,9 @@ */ public boolean add(E e) { typeCheck(e); - - long oldElements = elements; - elements |= (1L << ((Enum)e).ordinal()); - return elements != oldElements; + long oldElements = elems(); + System.setBit(bits, ((Enum)e).ordinal()); + return elems() != oldElements; } /** @@ -177,10 +201,9 @@ Class eClass = e.getClass(); if (eClass != elementType && eClass.getSuperclass() != elementType) return false; - - long oldElements = elements; - elements &= ~(1L << ((Enum)e).ordinal()); - return elements != oldElements; + long oldElements = elems(); + System.clrBit(bits, ((Enum)e).ordinal()); + return elems() != oldElements; } // Bulk Operations @@ -202,7 +225,7 @@ if (es.elementType != elementType) return es.isEmpty(); - return (es.elements & ~elements) == 0; + return (es.elems() & ~elems()) == 0; } /** @@ -225,10 +248,9 @@ throw new ClassCastException( es.elementType + " != " + elementType); } - - long oldElements = elements; - elements |= es.elements; - return elements != oldElements; + long oldElements = elems(); + setBits(elems() | es.elems()); + return elems() != oldElements; } /** @@ -246,10 +268,9 @@ RegularEnumSet es = (RegularEnumSet)c; if (es.elementType != elementType) return false; - - long oldElements = elements; - elements &= ~es.elements; - return elements != oldElements; + long oldElements = elems(); + setBits(elems() & ~es.elems()); + return elems() != oldElements; } /** @@ -266,21 +287,20 @@ RegularEnumSet es = (RegularEnumSet)c; if (es.elementType != elementType) { - boolean changed = (elements != 0); - elements = 0; + boolean changed = (elems() != 0); + setBits(0); return changed; } - - long oldElements = elements; - elements &= es.elements; - return elements != oldElements; + long oldElements = elems(); + setBits(elems() & es.elems()); + return elems() != oldElements; } /** * Removes all of the elements from this set. */ public void clear() { - elements = 0; + setBits(0); } /** @@ -298,7 +318,7 @@ RegularEnumSet es = (RegularEnumSet)o; if (es.elementType != elementType) - return elements == 0 && es.elements == 0; - return es.elements == elements; + return elems() == 0 && es.elems() == 0; + return es.elems() == elems(); } }